59

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

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

捕捉相机图像。因为我的应用程序想要离线运行,我如何将文件(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 :-(
}

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

我觉得它做不到,但我愿意接受建议。

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

4

7 回答 7

21

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

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

于 2013-10-05T14:24:07.650 回答
13

这是我使用下面的代码的一种解决方法。我知道您在编辑时谈到了 localStorage,但我想分享我是如何实际实施该解决方法的。我喜欢将函数放在主体上,这样即使之后通过 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 中,否则您可能会得到意想不到的结果。

于 2013-12-12T05:04:03.667 回答
13

将其转换为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
于 2017-01-01T15:59:00.490 回答
1

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

于 2013-12-18T20:31:45.193 回答
1

你可以使用这个库:

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"));
于 2013-10-05T14:11:25.473 回答
1

在全局范围内创建对象

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

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

于 2018-01-16T20:11:40.387 回答
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');
于 2019-06-24T14:16:50.227 回答