如何存储和检索图像到localStorage?

Ed *_*nes 15 javascript canvas jquery-mobile html5-canvas cordova

以为我有这个,但没有.目标:拍摄照片(保险卡),在本地保存,然后再检索.

// 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 );
Run Code Online (Sandbox Code Playgroud)

每一步都成功,最终输出是:

<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
Run Code Online (Sandbox Code Playgroud)

在新页面上,当我问

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

$('#TestScreen_mobileimage_1').src = policy_shot ;
Run Code Online (Sandbox Code Playgroud)

它记录二进制文件:

data:image/png;base64,iVBORw0KGgoAAAANSUhEUg ....
Run Code Online (Sandbox Code Playgroud)

但图像没有出现.

  1. 有更简单的方法吗?
  2. 为什么getItem(二进制)前面有数据:image/png; 而不是数据:image/jpg?
  3. 这就是为什么它没有显示,或者我做错了什么?

小智 13

1)这是你可以在本地将图像转换为字符串的唯一方法(使用FileReader加载的文件的拼写,见下文).您可以选择使用服务器来执行此操作.

2)要获得JPEG图像,您需要使用如下参数:

var datauri = imgCanvas.toDataURL("image/jpeg", 0.5); //0.5 = optional quality
Run Code Online (Sandbox Code Playgroud)

不要data:...在参数中使用,因为它将无效,并且它将产生您在结果中看到的默认PNG.toDataURL()只能采取一种类型,即.image/png,image/jpeg等等.

3)

外部文件

如果您的图像是从不同的来源(方案,服务器...)或使用本地引用的文件(等等)加载的file://,/my/path/CORS会启动并阻止您创建数据uri,即:图像将为空(因此不可见).

对于外部服务器,您可以通过提供crossOrigin属性来请求允许使用来自跨源的映像:

<img src="http://extrernalserver/...." crossOrigin="anonymous" />
Run Code Online (Sandbox Code Playgroud)

或者img.crossOrigin = 'anonymous';在设置之前通过code()src.

然而,服务器可以允许或拒绝请求.

如果它仍然不起作用,您将需要通过代理加载您的图像(例如,您的服务器上的一个页面可以从外部加载图像并从您自己的服务器提供它).

或者,如果您可以访问服务器的配置,则可以添加特殊访问允许标头(Access-Control-Allow-Origin: *有关详细信息,请参阅下面的链接).

CORS(跨源资源共享)是一种安全机制,除了这些方式之外无法解决.

本地文件

对于您需要使用的本地文件FileReader- 这可以证明是FileReader一个方便的方法:readAsDataURL().这允许您直接"上传"图像文件作为数据uri而不用画布.

请参阅此处的示例:https:
//developer.mozilla.org/en-US/docs/Web/API/FileReader

遗憾的是,您无法从代码中选择文件 - 您需要提供输入元素或放置区域,以便用户可以选择要存储的文件.

结论

如果所有这些步骤都达到了您实际获得图像的程度,则问题可能在另一端,截断的字符串太长而无法存储.

您可以通过检查存储字符串之前和之后的长度来验证是否已被剪切:

console.log(imgAsDataURL.length);
... set / get ...
console.log(pic.length);
Run Code Online (Sandbox Code Playgroud)

其他可能性:

  • 图像元素未正确定义.
  • 浏览器中的错误
  • 框架中的一个错误

(我想我涵盖了大部分典型的陷阱?)

更新(错过了一个,有点...... ;-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% - 因此空间将很少.查看索引数据库,Web SQL或文件API以获得更好的替代方案.