如何使以下readAsDataURL返回多个readAsDataURL?

时间:2017-06-13 02:44:51

标签: javascript file

此函数读取从输入字段获取的文件并返回其dataUrls:

readAsDataURL (target) {
  // target => <input type="file" id="file">
  var reader = new FileReader()
  return new Promise(function (resolve, reject) {
    reader.onload = function (event) {
      resolve(event.target.result)
    }
    reader.readAsDataURL(target.files[0])
  })
},

如您所见,该功能仅处理单个文件。我想要返回多个文件。我尝试了reader.readAsDataURL(target.files),但收到了此错误:'readAsDataURL' on 'FileReader': parameter 1 is not of type 'Blob'.

如何让函数返回多个dataUrls?

2 个答案:

答案 0 :(得分:2)

您是否尝试过使用Promise.all?您可以执行以下操作:

fileToDataURL(file) {
  var reader = new FileReader()
  return new Promise(function (resolve, reject) {
    reader.onload = function (event) {
      resolve(event.target.result)
    }
    reader.readAsDataURL(file)
  })
}  

readAsDataURL (target) {
  // target => <input type="file" id="file">
  var filesArray = Array.prototype.slice.call(target.files)      
  return Promise.all(filesArray.map(fileToDataURL))
}

这基本上与您设置的相同,但为每个创建一个承诺,只有在完成所有内容后才将结果返回到数组中。

我忘了您不能直接将target.files视为数组,因此需要先将其转换。为此,您可以使用:Array.prototype.slice.call(target.files)

答案 1 :(得分:2)

从问题中不清楚你对这些数据库有什么用处,但大多数时候,你实际上并不需要它。

为了能够将用户文件或Blob中的媒体显示到您的文档中,最好使用将返回blobURI的URL.createObjectURL()方法,您可以使用像任何网址一样。

blobURI优势的非详尽列表:

  • 是同步的。你不需要你的Promise包装事件处理程序地狱,所有这些都可以在一个循环中完成。
  • 快速。浏览器没有读取传递的文件或Blob,它只是在内存中创建一个符号链接到硬盘中的真实文件。
  • 是记忆重量。因为前一点。与readAsDataURL()相比,你应该注意后者将首先完全读取文件,将其转换为base64字符串(比原始数据大34%),最后,你将把这个大字符串存储在DOM& #39;标记,使其始终存在于内存中。从那时起,浏览器将再次读取它,将其转换为二进制文件,再次将其作为二进制文件读取,最后将其作为普通资源进行处理。

&#34;但我需要将其发送到服务器!&#34;

然后直接发送文件,作为多部分数据。如果你想在那里保存文件,那么前端的工作就会减少,管道中的工作量就会减少(记住~34%),而服务器端的工作就会减少。 大多数服务器端语言都有简单的内置方法来捕获POST请求中的文件,您可以使用FormData API从前面轻松发送。

以下是您的代码示例,使用blobURIs,它会将所有文件都视为图像。

&#13;
&#13;
document.querySelector('input').onchange = function(){
  // FileList doesn't have an forEach method yet
  Array.prototype.forEach.call(this.files, function(file){
    if(file.type.indexOf('image/' === 0)){
      var i = new Image();
      i.src = URL.createObjectURL(file);  // creates a blobURI
      document.body.appendChild(i);
      }
    });
  };
&#13;
<input type="file" multiple>
&#13;
&#13;
&#13;

但请注意,此方法也可以缺点

  • 不要在MediaStreams中使用它。它将锁定MediaStream的源,直到blobURI被撤销(在调用URL.revokeObject(blobURI)时或在页面的硬刷新时。在这种情况下,您应该使用mediaElement.srcObject = MediaStream;代替。
  • 对于您创建的Blob(不是来自<input>),同样适用:blob将被卡在内存中,直到明确释放。在这种情况下,只需在加载资源后调用URL.revokeObjectURL(blobURI)即可。

    img.onload = URL.revokeObjectURL(img.src); 
    img.src = URL.createObjectURL(the_Blob_I_built);