如何将图像存储和检索到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 ;
它记录二进制文件:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUg ....
但是图片没有出现.
- 有没有更简单的方法?
- 为什么getItem(二进制)前面是data:image/png;而不是 data:image/jpg ?
- 这是它不显示的原因,还是我做错了什么?
推荐答案
1) 这是您可以在本地将图像转换为字符串的唯一方法(除了使用 FileReader,见下文).(可选)您需要使用服务器来执行此操作.
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) 要获取 JPEG 图像,您需要使用如下参数:
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
不要在参数中使用 data:...
,因为这将是无效的,并且会生成默认的 PNG,正如您在结果中看到的那样.toDataURL()
只能接受一个类型,即.image/png
、image/jpeg
等
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)
如果您的图像是从不同的来源(方案、服务器...)或使用本地引用文件(file://
、/my/path/
等)CORS 启动并阻止您创建数据 uri,即:图像将为空(因此不可见).
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).
对于外部服务器,您可以通过提供 crossOrigin
属性来请求使用跨域图像的权限:
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" />
或在设置src
之前通过代码(img.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).
或者,如果您有权访问服务器的配置,则可以添加特殊的访问允许标头(Access-Control-Allow-Origin: *
,有关详细信息,请参阅下面的链接).
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 (跨域资源共享) 是一种安全机制,除此之外无法解决这些方法.
CORS (Cross-Origin Resource Sharing) is a security mechanism and can't be worked around other than these ways.
对于本地文件,您需要使用 FileReader
- 这可能是一个优势,因为 FileReader
带有一个方便的方法:readAsDataURL()代码>.这使您可以直接将图像文件上传"为数据 uri,而无需通过画布.
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.
在此处查看示例:
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.
如果所有这些步骤都完成到您确实获得图像的程度,那么问题可能出在另一端,被截断的字符串太长而无法存储.
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);
其他可能性:
- 图像元素未正确定义.
- 浏览器中的错误
- 框架中的一个错误
(我想我涵盖了大部分典型的陷阱?)
(I think I covered most of the typical pitfalls?)
更新(错过了一个,有点……;-p)
Update (missed one, sort of.. ;-p)
OP 在框架中找到了一个特定的内容,我将在此处包含以供将来参考:
OP found a specific in the framework which I'll include here for future reference:
最后,问题出在 $('#TestScreen_mobileimage_1').src =policy_shot ;
我正在使用 Appery.io,但它们不支持 .src
.
In the end, the issue was with
$('#TestScreen_mobileimage_1').src = policy_shot ;
I'm using Appery.io and they don't support.src
.
它是 $('#TestScreen_mobileimage_1').attr("src", policy_shot ) ;
最后一点:localStorage
在存储图像方面非常有限.典型存储空间为 2.5 - 5 mb.存储的每个 char 占用 2 个字节,并且存储编码为 base-64 的 data-uri 比原始数据大 33% - 所以空间将是稀缺的.查看 Indexed DB、Web SQL 或 File API 寻找好的替代方案.
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.
相关文章