如何在本地存储中保存和恢复 File 对象

IT技术 javascript html local-storage
2021-02-16 04:22:51

我有一个 HTML5/javscript 应用程序,它使用

<input type="file" accept="image/*;capture=camera" onchange="gotPhoto(this)">

捕捉相机图像。因为我的应用程序想要离线运行,我如何将 File ( https://developer.mozilla.org/en-US/docs/Web/API/File ) 对象保存在本地存储中,以便以后可以检索对于ajax上传?

我正在从 using 中获取文件对象...

function gotPhoto(element) { 
     var file = element.files[0];
     //I want to save 'file' to local storage here :-(
}

我可以将对象字符串化并保存,但是当我恢复它时,它不再被识别为 File 对象,因此不能用于获取文件内容。

我觉得它无法完成,但我愿意接受建议。

FWIW 我的解决方法是在存储时读取文件内容并将完整内容保存到本地存储。这有效,但很快就会消耗本地存储空间,因为每个文件都是 1MB 以上的照片。

6个回答

您不能序列化文件 API 对象。

并不是说它对特定问题有帮助,但是......虽然我没有使用过这个,如果你看这里似乎有办法(虽然大多数浏览器尚不支持)将离线图像数据存储到某些文件中以便在用户在线时恢复它们(而不是使用本地存储)

谢谢你的链接。一旦 Filesystem API 得到更好的支持,它可能会提供比 indexeddb 更好的替代方案。无论哪种方式,我最终都会得到图像的第二个副本(画廊中的原件和我保存在某处的副本),这是我试图避免的。但遗憾的是,我认为“您不能序列化文件 API 对象”是正确的答案。
2021-04-20 04:22:51
虽然我想你将它保存到 javascript blob,但我觉得使用隐藏的画布对象也有帮助,你可以在那里绘制图像数据,当你在线时从 canvas.data 获取图像数据。我想这个画布可能在 iframe 中?只要需要,它就可以持续存在(以免本地存储出现问题)。但是同样,只要您在 javascript 中拥有它,为什么还要将它放入画布对象中呢?
2021-04-22 04:22:51
问题是页面/浏览器重新加载。如果用户卸载页面,我将丢失存储在内存中的所有内容。
2021-05-07 04:22:51
是的,我明白,这就是您试图将其持久存储在其他地方的原因。我可以提到的另一件事是,为了拥有更多空间,您可以按顺序消耗浏览器的所有可用空间。我的意思是,例如,您可以按顺序使用本地存储、闪存、谷歌齿轮、即用户数据等(就像 Persistjs 那样但并行),但这需要大量编码。不管怎样,希望你能找到答案。
2021-05-09 04:22:51
由于明显的安全风险,这是不可能的。如果允许您将 File 对象作为字符串保存在本地存储中,您还可以修改该字符串以访问同一目录中的其他文件,而用户不知道。
2021-05-17 04:22:51

这是我使用以下代码的解决方法。我知道您在编辑中谈到了 localStorage,但我想分享我如何实际实施该解决方法。我喜欢将函数放在 body 上,这样即使之后通过 AJAX 添加类,“更改”命令仍会触发事件。

在此处查看我的示例:http : //jsfiddle.net/x11joex11/9g8NN/

如果您运行 JSFiddle 示例两次,您会看到它记住了图像。

我的方法确实使用了 jQuery。这种方法还演示了图像确实存在以证明其有效。

HTML:

<input class="classhere" type="file" name="logo" id="logo" />
<div class="imagearea"></div>

JS:

$(document).ready(function(){
  //You might want to do if check to see if localstorage set for theImage here
  var img = new Image();                
  img.src = localStorage.theImage;

  $('.imagearea').html(img);

  $("body").on("change",".classhere",function(){
      //Equivalent of getElementById
      var fileInput = $(this)[0];//returns a HTML DOM object by putting the [0] since it's really an associative array.
      var file = fileInput.files[0]; //there is only '1' file since they are not multiple type.

      var reader = new FileReader();
      reader.onload = function(e) {
           // Create a new image.
           var img = new Image();

           img.src = reader.result;
           localStorage.theImage = reader.result; //stores the image to localStorage
           $(".imagearea").html(img);
       }

       reader.readAsDataURL(file);//attempts to read the file in question.
    });
});

这种方法使用 HTML5 文件系统 API 来读取图像并将其放入新的 javascript img 对象中。这里的关键是 readAsDataURL。如果您使用 chrome 检查器,您会注意到图像以 base64 编码存储。

读取器是异步的,这就是它使用回调函数 onload 的原因。因此,请确保任何需要图像的重要代码都在 onLoad 内,否则您可能会得到意想不到的结果。

是的,我也在寻找你正在寻找的东西,我希望它可以完成,我悬赏以看看是否有人能解决这个问题。
2021-04-19 04:22:51
感谢您发布我确信会帮助人们的解决方法。我希望我可以编辑您的答案以强调它一种解决方法,而不是问题的答案。我一直在寻找一种方法来保存 File 对象,而无需制作图像数据的第二个副本。
2021-04-27 04:22:51
不,我想要整个 File 对象
2021-05-09 04:22:51
我特别希望保留 File对象,而不是文件内容我的应用面向移动设备,因此图片已保存在图库中。我想存储对图库图像的引用,而不是使用 localstorage 制作第二个副本,并具有所有大小限制。
2021-05-14 04:22:51
@pinoyyid 这是一种解决方法吗?它出什么问题了?
2021-05-17 04:22:51

将其转换为base64,然后保存。

function gotPhoto(element) {
   var file = element.files[0];
   var reader = new FileReader()
   reader.onload = function(base64) {
      localStorage["file"] = base64;
   }
   reader.readAsDataURL(file);
}
// Saved to localstorage

function getPhoto() {
   var base64 = localStorage["file"];
   var base64Parts = base64.split(",");
   var fileFormat = base64Parts[0].split(";")[1];
   var fileContent = base64Parts[1];
   var file = new File([fileContent], "file name here", {type: fileFormat});
   return file;
}
// Retreived file object
谢谢,但请再次阅读问题。我不想保存文件内容,我想保存 File 对象。
2021-04-30 04:22:51

你可以使用这个库:

https://github.com/carlo/jquery-base64

然后做类似的事情:

//Set file
var baseFile = $.base64.encode(fileObject);
window.localStorage.setItem("file",basefile);

//get file
var outFile = window.localStorage.getItem("file");

另一个解决方案是使用 json(我更喜欢这种方法)使用:http : //code.google.com/p/jquery-json/

//Set file
window.localStorage.setItem("file",$.toJSON(fileobject));

//get file
var outFile = $.evalJSON(window.localStorage.getItem("file"));
谢谢,但你已经错过了问题的重点。我不是在问如何保存任意的通用对象。我在问如何保存 File 对象,以便在恢复时它可以用作 File 对象。
2021-05-12 04:22:51

我不认为有直接的方法来字符串化然后将字符串对象反序列化为您感兴趣的对象。但作为一种解决方法,您可以将图像路径存储在本地存储中,并通过检索图像的 URL 来加载图像。优点是,您永远不会用完存储空间,并且可以在那里存储 1000 倍的文件。将图像或任何其他文件作为字符串保存在本地存储中从来都不是明智的决定。

你可以..你可以存储图像的路径,然后从本地存储加载它?是什么让你认为你不能?保留一个键作为别名并将图像文件的 url 存储为值.. 我已经在我的项目中做到了..
2021-04-26 04:22:51
Javascript 安全模型不允许从本地驱动器读取文件。
2021-05-01 04:22:51
“您可以将图像路径存储在本地存储中,并通过检索图像的 URL 来加载图像”。不,你不能
2021-05-02 04:22:51