如何在本地存储中保存和还原File对象

时间:2013-10-01 14:36:25

标签: javascript html5 local-storage

我有一个使用

的HTML5 / javscript应用程序
<input type="file" accept="image/*;capture=camera" onchange="gotPhoto(this)">

捕捉相机图像。由于我的应用程序希望脱机运行,如何将文件(https://developer.mozilla.org/en-US/docs/Web/API/File)对象保存在本地存储中,以便稍后可以检索它以进行ajax上载?

我从使用中抓取文件对象...

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

我可以对对象进行String化并保存,但是当我恢复它时,它不再被识别为File对象,因此无法用于获取文件内容。

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

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

7 个答案:

答案 0 :(得分:11)

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

请参阅我的示例: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中,否则您可能会得到意想不到的结果。

答案 1 :(得分:9)

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

不是它有助于解决具体问题,但...... 虽然我没有使用过这个,但是如果看一下here,似乎有一些方法(大多数浏览器还没有支持)将离线图像数据存储到某些文件中,以便在用户访问后再恢复它们。在线(而不是使用localstorage)

答案 2 :(得分:5)

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

答案 3 :(得分:1)

您可以使用此lib:

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

答案 4 :(得分:1)

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

答案 5 :(得分:0)

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

exp: var attmap = new Object();

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

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

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

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

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

EncodingUtil.base64Decode(CurrentMapValue);

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

答案 6 :(得分:0)

您可以执行以下操作:

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

然后您可以做:

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