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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19017401/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 14:04:48  来源:igfitidea点击:

How to store and retrieve image to localStorage?

javascriptcordovajquery-mobilecanvashtml5-canvas

提问by Ed Jones

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?
  1. 有没有更简单的方法?
  2. 为什么getItem(二进制)前面是data:image/png;而不是 data:image/jpg ?
  3. 这就是它不显示的原因,还是我做错了什么?

采纳答案by Ed Jones

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.

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

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

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

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/jpegetc.

不要data:...在参数中使用,因为这将是无效的,它会产生默认的 PNG,如您在结果中看到的那样。toDataURL()只能采用一种类型,即。image/pngimage/jpeg等等。

3)

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).

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

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

对于外部服务器,您可以通过提供以下crossOrigin属性来请求使用来自跨域的图像的权限:

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

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

img.crossOrigin = 'anonymous';在设置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).

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

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

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

Local files

本地文件

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

对于您需要使用的本地文件FileReader- 这可能FileReader是一个方便的方法带来的优势:readAsDataURL(). 这允许您直接将图像文件“上传”为数据 uri,而无需通过画布。

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

请参阅此处的示例: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)

更新(错过了一个,有点……;-p)

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

OP 在框架中找到了一个特定的内容,我将在此处包含以供将来参考:

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

最后,问题出在$('#TestScreen_mobileimage_1').src = policy_shot ;我使用 Appery.io 而他们不支持.src.

它是 $('#TestScreen_mobileimage_1').attr("src", policy_shot ) ;

A final note: localStorageis 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.

最后一点:localStorage在存储图像方面非常有限。典型的存储空间为 2.5 - 5 mb。存储的每个字符需要 2 个字节,并且存储编码为 base-64 的数据 uri 比原始字符大 33% - 因此空间将变得稀缺。查看索引数据库、Web SQL 或文件 API 以获得好的替代方案。

回答by Dmitry Sheiko

Here the complete solution using File Api

这里使用 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" ),
          /** Restore image src from local storage */
          updateUi = function() {
            imgContainer.src = window.localStorage.getItem( "image-base64" );
          },
          /** Register event listeners */
          bindUi = function(){
            imgInput.addEventListener( "change", function(){
              if ( this.files.length ) {
                var reader = new FileReader();
                reader.onload = function( e ){
                  window.localStorage.setItem( "image-base64", e.target.result );
                  updateUi();
                };
                reader.readAsDataURL( this.files[ 0 ] );
              }
            }, false );
          };

    updateUi();
    bindUi();
    }());
    </script>
    </body>
    </html>