web-dev-qa-db-ja.com

localStorageに画像を保存して取得する方法は?

私はこれを持っていると思ったが、持っていなかった。目標は、写真(保険カード)をスナップしてローカルに保存し、後で取得することです。

// Get a reference to the image element
var elephant = document.getElementById("SnapIt_mobileimage_5");

var imgCanvas = document.createElement("canvas"),
imgContext = imgCanvas.getContext("2d");

// Make sure canvas is as big as the picture
imgCanvas.width = elephant.width;
imgCanvas.height = elephant.height;

// Draw image into canvas element

imgContext.drawImage(elephant, 0, 0, elephant.width, elephant.height );
 console.log( 'Did that' );
// Get canvas contents as a data URL
var imgAsDataURL = imgCanvas.toDataURL("data:image/jpg;base64,");

// Save image into localStorage
try {
localStorage.setItem("elephant", imgAsDataURL);
}
catch (e) {
console.log("Storage failed: " + e);
}; 

//Did it work?
var pic = localStorage.getItem("elephant");

console.log( elephant );
console.log( pic );

各ステップが成功すると、最終的な出力は次のようになります。

<img id="SnapIt_mobileimage_5" class=" SnapIt_mobileimage_5" name="mobileimage_5" dsid="mobileimage_5" src="files/views/assets/image/IMG_0590.JPG">
 data:image/png;base64,iVBORw0KGgoAAAANSUhEUgA

新しいページで、私が尋ねたとき

var policy_shot = localStorage.getItem( 'elephant' );
console.log( policy_shot );

$('#TestScreen_mobileimage_1').src = policy_shot ;

バイナリをログに記録します。

data:image/png;base64,iVBORw0KGgoAAAANSUhEUg ....

しかし、画像は表示されません。

  1. より簡単なアプローチはありますか?
  2. GetItem(バイナリ)の前にdata:image/pngがあるのはなぜですか。 data:image/jpgの代わりに?
  3. それが表示されないのはなぜですか、それとも何か他の問題がありますか?
16
Ed Jones

1)これは、イメージをローカルで文字列に変換できる唯一の方法です(- FileReader でロードされたファイルを除いて) 、 下記参照)。オプションで、サーバーを使用して実行する必要があります。

2)JPEG画像を取得するには、次のような引数を使用する必要があります。

_var datauri = imgCanvas.toDataURL("image/jpeg", 0.5); //0.5 = optional quality
_

引数に_data:..._を使用しないでください。これは無効になり、結果からわかるようにデフォルトのPNGが生成されます。 toDataURL()は型のみを取ることができます。 _image/png_、_image/jpeg_など.

3)

外部ファイル

画像が別のOrigin(スキーム、サーバーなど)から、またはローカル参照ファイル(_file://_、_/my/path/_など)を使用してロードされた場合、CORSが起動し、データを作成できなくなります- uri、つまり、画像は空になります(そのため非表示になります)。

外部サーバーの場合、crossOriginプロパティを指定することにより、クロスオリジンのイメージを使用する権限をリクエストできます。

_<img src="http://extrernalserver/...." crossOrigin="anonymous" />
_

または、srcを設定する前にコード(_img.crossOrigin = 'anonymous';_)を使用します。

ただし、リクエストを許可または拒否するのはサーバーの責任です。

それでも機能しない場合は、プロキシを介して画像をロードする必要があります(f.exは、画像を外部にロードして自分のサーバーから提供できるサーバー上のページなど)。

または、サーバーの構成にアクセスできる場合は、特別なアクセス許可ヘッダーを追加できます(_Access-Control-Allow-Origin: *_。詳細については、以下のリンクを参照してください)。

CORS( Cross-Origin Resource Sharing )はセキュリティメカニズムであり、これらの方法以外では回避できません。

ローカルファイル

ローカルファイルの場合はFileReaderを使用する必要があります-FileReaderには便利なメソッドreadAsDataURL()が付属しているため、これは利点になる可能性があります。これにより、キャンバスを経由せずに、画像ファイルをデータURIとして直接「アップロード」できます。

こちらの例をご覧ください:
https://developer.mozilla.org/en-US/docs/Web/API/FileReader

残念ながら、コードからファイルを選択することはできません。ユーザーが保存したいファイルを選択できるように、入力要素またはドロップゾーンを提供する必要があります。

結論

これらのすべての手順が実際に画像を取得する程度に満たされている場合、問題はおそらくもう一方の端にあり、切り捨てられる文字列は長すぎて格納できません。

文字列を保存する前後に長さをチェックして、文字列がカットされているかどうかを確認できます。

_console.log(imgAsDataURL.length);
... set / get ...
console.log(pic.length);
_

その他の可能性:

  • 画像要素が正しく定義されていません。
  • ブラウザのバグ
  • フレームワークのバグ

(私は典型的な落とし穴のほとんどをカバーしたと思いますか?)

Update(1つ欠落、並べ替え.. ;-p)

OPはフレームワークで特定のものを見つけました。将来の参照のためにここに含めます。

結局、問題は$('#TestScreen_mobileimage_1').src = policy_shot ;にありました。Appery.ioを使用していますが、_.src_はサポートされていません。

それは$('#TestScreen_mobileimage_1').attr("src", policy_shot ) ;です

最後の注記:localStorageは、イメージの保存に関して非常に制限されています。典型的な収納スペースは2.5-5 mbです。格納される各文字は2バイトを必要とし、base-64としてエンコードされたデータURIを格納すると、元の文字より33%大きいため、スペースが不足します。優れた代替策については、インデックス付きDB、Web SQL、またはFile APIを調べてください。

12
user1693593

ここでFile Apiを使用した完全なソリューション

 
 <html> 
 <body> 
 <input type = "file" id = "image-input" />
 <img id = "image-container" />
 <script type = "text/javascript"> 
(function(){
/** @type {Node} */
 var imgInput = document.getElementById( "image-input")、
/** @type {Node} */
 imgContainer = document.getElementById( "image-container")、 
/**ローカルストレージからイメージsrcを復元*/
 updateUi = function(){
 imgContainer.src = window.localStorage.getItem( "image-base64"); 
}、
/**イベントリスナーを登録*/
 bindUi = function(){
 imgInput.addEventListener( "change"、function(){
 if(this.files.length){
 var reader = new FileReader(); 
 reader.onload = function(e){
 window.localStorage.setItem( " ima ge-base64 "、e.target.result); 
 updateUi(); 
}; 
 reader.readAsDataURL(this.files [0]); 
 } 
}、false); 
}; 
 
 updateUi(); 
 bindUi(); 
}()) ; 
 </ script> 
 </ body> 
 </ html> 
 
2
Dmitry Sheiko