Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
170 views
in Technique[技术] by (71.8m points)

javascript - How to store and retrieve image to localStorage?

Thought I had this, but no. The goal: snap a photo (insurance card), save it locally, and retrieve it later.

// 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 );

Each step succeeds, the final output is:

<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

On a new page, when I ask

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

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

It logs the binary:

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

But the image doesn't appear.

  1. Is there a simpler approach?
  2. Why is the getItem (binary) preceded by data:image/png; instead of data:image/jpg ?
  3. Is that why it doesn't display, or am I doing something else wrong?
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

1) This is the only way you can convert an image into a string locally (with the excpetion of files loaded with FileReader, see below). Optionally you need to use the server to do it.

2) To get a JPEG image you need to use the argument like this:

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

don't use data:... in the argument as that will be invalid and it will produce the default PNG as you can see in your result. toDataURL() can only take a type, ie. image/png, image/jpeg etc.

3)

External files

If your image was loaded from a different origin (scheme, server ...) or by using local referenced files (file://, /my/path/ etc.) CORS kicks in and will prevent you from creating a data-uri, that is: the image will be empty (and therefor invisible).

For external servers you can request permission to use the image from a cross-origin by supplying the crossOrigin property:

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

or by code (img.crossOrigin = 'anonymous';) before setting the src.

It's however up to the server to allow or deny the request.

If it still doesn't work you will need to load your image through a proxy (f.ex. a page on your server that can load and the image externally and serve it from your own server).

Or if you have access to the server's configuration you can add special access allow headers (Access-Control-Allow-Origin: *, see link below for more details).

CORS (Cross-Origin Resource Sharing) is a security mechanism and can't be worked around other than these ways.

Local files

For local files you will need to use FileReader - this can turn out to be an advantage as FileReader comes with a handy method: readAsDataURL(). This allow you to "upload" the image file directly as a data-uri without going by canvas.

See examples here:
https://developer.mozilla.org/en-US/docs/Web/API/FileReader

Unfortunately you can't just pick the files from code - you will need to provide an input element or a drop zone so the user can pick the files (s)he want to store.

Conclusion

If all these steps are fulfilled to the degree that you actually do get an image the problem possibly is in the other end, the string being truncated being too long to store.

You can verify by checking the length before and after storing the string to see if it has been cut:

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

Other possibilities:

  • The image element is not properly defined.
  • A bug in the browser
  • A bug in the framework

(I think I covered most of the typical pitfalls?)

Update (missed one, sort of.. ;-p)

OP found a specific in the framework which I'll include here for future reference:

In the end, the issue was with $('#TestScreen_mobileimage_1').src = policy_shot ; I'm using Appery.io and they don't support .src.

It's $('#TestScreen_mobileimage_1').attr("src", policy_shot ) ;

A final note: localStorage is very limited in regards to storing images. Typical storage space is 2.5 - 5 mb. Each char stored takes 2 bytes and storing a data-uri encoded as base-64 is 33% larger than the original - so space will be scarce. Look into Indexed DB, Web SQL or File API for good alternatives.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...