16

以为我有这个,但没有。目标:拍一张照片(保险卡),将其保存在本地,稍后再检索。

// 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. 这就是它不显示的原因,还是我做错了什么?
4

2 回答 2

13

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

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

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

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

3)

外部文件

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

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

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

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

其他可能性:

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

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

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

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

最后,问题出在$('#TestScreen_mobileimage_1').src = policy_shot ;我使用的是 Appery.io 而他们不支持.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 寻找好的替代方案。

于 2013-09-26T00:44:32.227 回答
2

这里是使用 File Api 的完整解决方案

    <html>
    <正文>
    <input type="file" id="image-input" />
    <img id="图像容器" />
    <script type="text/javascript">
    (功能(){
          /** @type {节点} */
      var imgInput = document.getElementById("图像输入"),
          /** @type {节点} */
          imgContainer = document.getElementById("图像容器"),
          /** 从本地存储恢复镜像 src */
          updateUi = 函数() {
            imgContainer.src = window.localStorage.getItem("image-base64");
          },
          /** 注册事件监听器 */
          bindUi = 函数(){
            imgInput.addEventListener(“改变”,函数(){
              如果(this.files.length){
                var reader = new FileReader();
                reader.onload = 函数(e){
                  window.localStorage.setItem("image-base64", e.target.result);
                  更新Ui();
                };
                reader.readAsDataURL(this.files[0]);
              }
            }, 错误的 );
          };

    更新Ui();
    绑定UI();
    }());
    </脚本>
    </正文>
    </html>

于 2014-03-06T11:23:24.127 回答