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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19119040/
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-08-29 14:00:28  来源:igfitidea点击:

How do I save and restore a File object in local storage

javascripthtmllocal-storage

提问by pinoyyid

I have an HTML5/javscript app which uses

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

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

to capture a camera image. Because my app wants to be runnable offline, how do I save the File (https://developer.mozilla.org/en-US/docs/Web/API/File) object in local storage, such that it can be retrieved later for an ajax upload?

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

I'm grabbing the file object from the using ...

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

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

I can Stringify the object and save it, but when I restore it, it is no longer recognised as a File object, and thus can't be used to grab the file content.

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

I have a feeling it can't be done, but am open to suggestions.

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

FWIW My workaround is to read the file contents at store time and save the full contents to local storage. This works, but quickly consumes local storage since each file is a 1MB plus photograph.

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

采纳答案by George Mavritsakis

You cannot serialize file API object.

您无法序列化文件 API 对象。

Not that it helps with the specific problem, but ... Although I haven't used this, if you look hereit seems that there are ways (althought not supported yet by most browsers) to store the offline image data to some files so as to restore them afterwards when the user is online (and not to use localstorage)

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

回答by Joseph Astrahan

Here is a workaround that I got working with the code below. I'm aware with your edit you talked about localStorage but I wanted to share how I actually implemented that workaround. I like to put the functions on body so that even if the class is added afterwards via AJAX the "change" command will still trigger the event.

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

See my example here: http://jsfiddle.net/x11joex11/9g8NN/

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

If you run the JSFiddle example twice you will see it remembers the image.

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

My approach does use jQuery. This approach also demonstrates the image is actually there to prove it worked.

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

HTML:

HTML:

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

JS:

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

This approach uses the HTML5 File System API's to read the image and put it into a new javascript img object. The key here is readAsDataURL. If you use chrome inspector you will notice the images are stored in base64 encoding.

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

The reader is Asynchronous, this is why it uses the callback function onload. So make sure any important code that requires the image is inside the onLoad or else you may get unexpected results.

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

回答by The helpful coding genius

Convert it to base64 and then save it.

将其转换为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

回答by Jashobanta Chakraborty

I don't think that there is a direct way to Stringify and then deserialize the string object into the object of your interest. But as a work around you can store the image paths in your local storage and load the images by retrieving the URL for the images. Advantages would be, you will never run out of storage space and you can store 1000 times more files there.. Saving an image or any other file as a string in local storage is never a wise decision..

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

回答by Philip G

You could use this lib:

你可以使用这个库:

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

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

then do something similar to this:

然后做类似的事情:

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

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

an other solution would be using json (I prefer this method) using: http://code.google.com/p/jquery-json/

另一个解决方案是使用 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"));

回答by umithuckan

create an object on the global scope

在全局范围内创建一个对象

exp: var attmap = new Object();

after you are done with file selection, put your files in attmap variable as below,

完成文件选择后,将文件放入 attmap 变量中,如下所示,

attmap[file.name] = attachmentBody;
JSON.stringify(attmap)

Then you can send it to controller via input hidden or etc. and use it after deserializing.

然后您可以通过输入隐藏等将其发送到控制器并在反序列化后使用它。

(Map<String, String>)JSON.deserialize(attachments, Map<String,String>.class);

You can create your files with those values in a for loop or etc.

您可以在 for 循环等中使用这些值创建文件。

EncodingUtil.base64Decode(CurrentMapValue);

FYI:This solution will also cover multiple file selection

仅供参考:此解决方案还将涵盖多个文件选择

回答by Dryden Williams

You could do something like this:

你可以这样做:

// fileObj = new File(); from file input
const buffer = Buffer.from(await new Response(fileObj).arrayBuffer());
const dataUrl = `data:${fileObj.type};base64,${buffer.toString("base64")}`;

localStorage.setItem('dataUrl', dataUrl);

then you can do:

那么你可以这样做:

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