web-dev-qa-db-ja.com

ローカルストレージにFileオブジェクトを保存および復元する方法

を使用するHTML5/javscriptアプリがあります

<input type="file" accept="image/*;capture=camera" onchange="gotPhoto(this)">

カメラ画像をキャプチャします。私のアプリはオフラインで実行できるようにしたいので、ローカルストレージにFile( https://developer.mozilla.org/en-US/docs/Web/API/File )オブジェクトを保存するにはどうすればよいですか。後でAjaxアップロードのために取得できるように?

私は使用からファイルオブジェクトを取得しています...

function gotPhoto(element) { 
     var file = element.files[0];
     //I want to save 'file' to local storage here :-(
}

オブジェクトを文字列化して保存することはできますが、復元すると、Fileオブジェクトとして認識されなくなり、ファイルの内容を取得するために使用できなくなります。

私はそれを行うことができないと感じていますが、提案を受け入れています。

FWIW回避策は、保存時にファイルの内容を読み取り、ローカルストレージに内容全体を保存することです。これは機能しますが、各ファイルは1MB以上の写真であるため、ローカルストレージをすぐに消費します。

36
pinoyyid

ファイルAPIオブジェクトをシリアル化することはできません。

特定の問題に役立つわけではありませんが、...これを使用していませんが、 here を見ると、(ほとんどのブラウザではまだサポートされていませんが)オフラインの画像データをいくつかのファイルに保存して、ユーザーがオンラインになったときにそれらを復元できるようにします(localstorageを使用しません)

9

以下は、以下のコードで作業した回避策です。あなたがあなたがlocalStorageについて話した編集には気づいていますが、私は実際にその回避策をどのように実装したかを共有したかったです。 AJAXを介してクラスが後で追加されても、 "change"コマンドがイベントをトリガーするように、関数をbodyに配置するのが好きです。

ここに私の例を参照してください: http://jsfiddle.net/x11joex11/9g8NN/

JSFiddleの例を2回実行すると、イメージが記憶されていることがわかります。

私のアプローチではjQueryを使用しています。また、このアプローチは、イメージが実際に存在し、それが機能したことを証明することを示しています。

HTML:

<input class="classhere" type="file" name="logo" id="logo" />
<div class="imagearea"></div>

JS:

$(document).ready(function(){
  //You might want to do if check to see if localstorage set for theImage here
  var img = new Image();                
  img.src = localStorage.theImage;

  $('.imagearea').html(img);

  $("body").on("change",".classhere",function(){
      //Equivalent of getElementById
      var fileInput = $(this)[0];//returns a HTML DOM object by putting the [0] since it's really an associative array.
      var file = fileInput.files[0]; //there is only '1' file since they are not multiple type.

      var reader = new FileReader();
      reader.onload = function(e) {
           // Create a new image.
           var img = new Image();

           img.src = reader.result;
           localStorage.theImage = reader.result; //stores the image to localStorage
           $(".imagearea").html(img);
       }

       reader.readAsDataURL(file);//attempts to read the file in question.
    });
});

このアプローチでは、HTML5ファイルシステムAPIを使用して画像を読み取り、新しいjavascript imgオブジェクトに配置します。ここでのキーはreadAsDataURLです。 chromeインスペクターを使用すると、画像がbase64エンコーディングで保存されていることがわかります。

リーダーは非同期です。これがコールバック関数onloadを使用する理由です。したがって、イメージを必要とする重要なコードがonLoad内にあることを確認してください。そうしないと、予期しない結果が生じる可能性があります。

11
Joseph Astrahan

Base64に変換して保存します。

function gotPhoto(element) {
var file = element.files[0];
var reader = new FileReader()
reader.onload = function(base64) {
localStorage["file"] = base64;
}
reader.readAsDataURL(file);
}
// Saved to localstorage
function getPhoto() {
var base64 = localStorage["file"];
var base64Parts = base64.split(",");
var fileFormat = base64Parts[0].split(";")[1];
var fileContent = base64Parts[1];
var file = new File([fileContent], "file name here", {type: fileFormat});
return file;
}
// Retreived file object

このライブラリを使用できます:

https://github.com/carlo/jquery-base64

次に、これに似た何かをします:

//Set file
var baseFile = $.base64.encode(fileObject);
window.localStorage.setItem("file",basefile);

//get file
var outFile = window.localStorage.getItem("file");

他の解決策は、jsonを使用することです(私はこの方法を好みます): http://code.google.com/p/jquery-json/

//Set file
window.localStorage.setItem("file",$.toJSON(fileobject));

//get file
var outFile = $.evalJSON(window.localStorage.getItem("file"));
1
Philip G

文字列オブジェクトを文字列化してから目的のオブジェクトにデシリアライズする直接的な方法はないと思います。ただし、回避策として、ローカルストレージに画像パスを保存し、画像のURLを取得して画像を読み込むことができます。利点は、ストレージスペースがなくなることはなく、1000倍以上のファイルをそこに保存できることです。ローカルストレージにイメージまたはその他のファイルを文字列として保存することは賢明な決定ではありません。

グローバルスコープにオブジェクトを作成します

exp: var attmap = new Object();

ファイルの選択が完了したら、次のようにattmap変数にファイルを入れます。

attmap[file.name] = attachmentBody;
JSON.stringify(attmap)

その後、入力隠しなどを介してコントローラーに送信し、デシリアライズ後に使用できます。

(Map<String, String>)JSON.deserialize(attachments, Map<String,String>.class);

Forループなどでこれらの値を使用してファイルを作成できます。

EncodingUtil.base64Decode(CurrentMapValue);

参考:このソリューションは、複数のファイル選択もカバーします

0
umithuckan

次のようなことができます:

// fileObj = new File(); from file input
const buffer = Buffer.from(await new Response(fileObj).arrayBuffer());
const dataUrl = `data:${fileObj.type};base64,${buffer.toString("base64")}`;

localStorage.setItem('dataUrl', dataUrl);

その後、次のことができます:

document.getElementById('image').src = localStorage.getItem('dataUrl');
0
Dryden Williams