如何将图像保存到 localStorage 并在下一页显示?

Posted

技术标签:

【中文标题】如何将图像保存到 localStorage 并在下一页显示?【英文标题】:How to save an image to localStorage and display it on the next page? 【发布时间】:2013-10-11 13:37:06 【问题描述】:

所以,基本上,我需要上传一张图片,保存到localStorage,然后在下一页显示。

目前,我有我的 html 文件上传:

<input type='file' id="uploadBannerImage" onchange="readURL(this);" />

利用这个函数在页面上显示图片

function readURL(input) 

    document.getElementById("bannerImg").style.display = "block";

    if (input.files && input.files[0]) 
        var reader = new FileReader();

        reader.onload = function (e) 
            document.getElementById('bannerImg').src =  e.target.result;
        

        reader.readAsDataURL(input.files[0]);
    

图像会立即显示在页面上供用户查看。然后要求他们填写表格的其余部分。这部分运行良好。

一旦表格完成,他们就会按下“保存”按钮。按下此按钮后,我将所有表单输入保存为localStorage 字符串。我还需要一种方法将图像另存为 localStorage 项目。

保存按钮也会将他们引导至新页面。这个新页面将在表格中显示用户数据,图片位于顶部。

如此简单明了,一旦按下“保存”按钮,我需要将图像保存在localStorage,然后从localStorage 借出下一页图像。

我找到了一些解决方案,例如this fiddle和this article at moz://a HACKS。

虽然我仍然对它的工作原理感到非常困惑,但我真的只需要一个简单的解决方案。基本上,我只需要在按下“保存”按钮后通过getElementByID 找到图像,然后处理并保存图像。

【问题讨论】:

像这个例子一样将 reader.result 存储在 localstorage 中有什么问题:jsfiddle.net/x11joex11/9g8NN? 对于希望在 localStorage 上存储大量数据的人来说,这个库非常棒:pieroxy/lz-string: LZ-based compression algorithm for javascript “我只需要一个简单的解决方案。”每个人都不行吗? 【参考方案1】:

要将图像存储在 localStorage 中并稍后重新加载,我使用了已接受的答案、James H. Kelly 的评论和 FileReader object 的组合。

我首先使用 FileReader 对象将上传的图像存储为 Base64 字符串:

// get user's uploaded image
const imgPath = document.querySelector('input[type=file]').files[0];
const reader = new FileReader();

reader.addEventListener("load", function () 
    // convert image file to base64 string and save to localStorage
    localStorage.setItem("image", reader.result);
, false);

if (imgPath) 
    reader.readAsDataURL(imgPath);

然后,要从 localStorage 中读回图像,我只需执行以下操作:

let img = document.getElementById('image');
img.src = localStorage.getItem('image');

【讨论】:

【参考方案2】:

如果您的图像不断被裁剪,这里有一些代码可以在保存到本地存储之前获取图像文件的尺寸。

首先,我会创建一些隐藏的输入框来保存宽度和高度值

<input id="file-h" hidden type="text"/>
<input id="file-w" hidden type="text"/>

然后将文件的尺寸输入到输入框中

var _URL = window.URL || window.webkitURL;
$("#file-input").change(function(e) 
    var file, img;
    if ((file = this.files[0])) 
        img = new Image();
        img.onload = function() 
            $("#file-h").val(this.height);
            $("#file-w").val(this.width);
        ;
        img.onerror = function() 
            alert( "not a valid file: " + file.type);
        ;
        img.src = _URL.createObjectURL(file);
    
);

最后,通过指向您的输入框值来更改 getBase64Image() 函数中使用的宽度和高度对象

来自

function getBase64Image(img) 
    var canvas = document.createElement("canvas");
    canvas.width = img.width;
    canvas.height = img.height;

function getBase64Image(img) 
    var canvas = document.createElement("canvas");
    canvas.width = $("#file-w").val();
    canvas.height = $("#file-h").val();

此外,您必须为所有文件保持大约 300kb 的大小。 *** 上有一些帖子涉及使用 Javascript 进行文件大小验证。

【讨论】:

【参考方案3】:
document.getElementById('file').addEventListener('change', (e) => 
  const file = e.target.files[0];
  const reader = new FileReader();
  reader.onloadend = () => 
    // convert file to base64 String
    const base64String = reader.result.replace('data:', '').replace(/^.+,/, '');
    // store file
    localStorage.setItem('wallpaper', base64String);
    // display image
    document.body.style.background = `url(data:image/png;base64,$base64String)`;
  ;
  reader.readAsDataURL(file);
);

Example CodePen

【讨论】:

【参考方案4】:

致同样需要解决此问题的人:

首先,我使用getElementByID 抓取我的图像,并将图像保存为 Base64。然后我将 Base64 字符串保存为我的 localStorage 值。

bannerImage = document.getElementById('bannerImg');
imgData = getBase64Image(bannerImage);
localStorage.setItem("imgData", imgData);

这是将图像转换为 Base64 字符串的函数:

function getBase64Image(img) 
    var canvas = document.createElement("canvas");
    canvas.width = img.width;
    canvas.height = img.height;

    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0);

    var dataURL = canvas.toDataURL("image/png");

    return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");

然后,在我的下一页上,我创建了一个带有空白 src 的图像,如下所示:

<img src="" id="tableBanner" />

当页面加载时,我使用接下来的三行从 localStorage 获取 Base64 字符串,并将其应用到带有我创建的空白 src 的图像:

var dataImage = localStorage.getItem('imgData');
bannerImg = document.getElementById('tableBanner');
bannerImg.src = "data:image/png;base64," + dataImage;

在很多不同的浏览器和版本中测试过,效果不错。

【讨论】:

不支持gif,因为canvas不支持gif。 您不需要 getBase64Image 函数。数据 url 已经是 base 64,所以当你调用 reader.readAsDataURL 时,发送到 reader.onload 处理程序的 e.target.result 将是你所需要的。 请记住,本地/会话存储的限制约为 5MB。将二进制图像转换为 base 64 编码的字符串将使其大 30% 左右。所以这不适用于高分辨率图像。 为什么要去掉数据url的开头部分?缩小尺寸? 请注意,您需要先完全加载图像(否则最终会出现空图像),因此在某些情况下您需要将处理包装到:bannerImage.addEventListener("load", function () );【参考方案5】:

我提出了同样的问题,而不是存储最终溢出本地存储的图像,您可以只存储图像的路径。 类似:

let imagen = ev.target.getAttribute('src');
arrayImagenes.push(imagen);

【讨论】:

【参考方案6】:

"请注意,您需要先完全加载图像(否则最终会出现空图像),因此在某些情况下您需要将处理包装到:bannerImage.addEventListener("load", function () ); – yuga 2017 年 11 月 1 日 13:04"

这非常重要。我今天下午正在探索的选项之一是使用 javascript 回调方法而不是 addEventListeners,因为它似乎也没有正确绑定。在不刷新页面的情况下在页面加载之前准备好所有元素是至关重要的。

如果有人可以对此进行扩展,请执行 - 例如,您是否使用了 settimeout、等待、回调或 addEventListener 方法来获得所需的结果。哪一个?为什么?

【讨论】:

如果可以,请始终使用回调,如果可以避免,请永远不要使用 settimeout。按照设计,您希望这件事发生在前一件事之后,并且开销尽可能少。这正是回调的设计目的【参考方案7】:

我在 localStorage JQueryImageCaching 中写了一个 2,2kb 的小图片保存库 用法:

<img data-src="path/to/image">
<script>
    $('img').imageCaching();
</script>

【讨论】:

2.2 KB 对于这样的事情来说是巨大的,而且我猜这甚至不考虑 jQuery 本身的大小。我建议不使用 jQuery 编写它,也许它会更小 1.74 KB 根据 gitbub【参考方案8】:

您可以将图像序列化为数据 URI。这个blog post 中有一个教程。这将产生一个可以存储在本地存储中的字符串。然后在下一页,使用数据 uri 作为图像的来源。

【讨论】:

以上是关于如何将图像保存到 localStorage 并在下一页显示?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 JWT 保存到 localStorage

将 HTML5 画布图像保存到数据库

如何将引用的js脚本保存到 localstrage 里面

将令牌保存在 localStorage 和拦截器中

如何使用 LocalStorage 将 json 对象保存到 Assets 文件夹

如何将sidenav(mat-drawer)状态保存到Angular Material中的localstorage?