使用FileReader和FormData上传文件有什么区别?

5
使用 Ajax(XHR2)上传文件有两种方式。首先,我可以将文件内容读取为数组缓冲区或二进制字符串,然后使用 XHR 的 send 方法进行简单的流式传输。例如,如此处所示
function uploadFile(img, file) {
  const reader = new FileReader();
  const xhr = new XMLHttpRequest();

  xhr.upload.addEventListener("progress", function(e) {
        if (e.lengthComputable) {
          const percentage = Math.round((e.loaded * 100) / e.total);
          // Do something with percentage
        }
      });

  xhr.upload.addEventListener("load", (e) => console.log('Do something more'));

  xhr.open("POST", "some-url");
  xhr.overrideMimeType('text/plain; charset=x-user-defined-binary');

  reader.onload = function(evt) {
    xhr.send(evt.target.result);
  };
  reader.readAsBinaryString(file);
}

其次,我可以使用 FormData 对象以 下面示例中所示的方式 上传文件:

var formData = new FormData();

// HTML file input, chosen by user
formData.append("userfile", fileInputElement.files[0]);

var request = new XMLHttpRequest();

request.open("POST", "some-url");

request.send(formData);

这两种方法是否等效?使用FileReader是否有任何优势,而不是FormData?它们中哪一个更高效?


看起来文件读取器是流式的,因此对于大型文件更有用。 - flup
1个回答

7

首先,你遗漏了第三个选项,即像处理ArrayBuffer一样直接通过xhr.send(file)发送文件。

也就是说,通过FileReader首先将文件读取到内存中并没有任何优点。


从磁盘上传文件时,浏览器不会将整个文件加载到内存中,而是通过请求进行流式传输。这就是你可以上传数GB数据的原因,即使它无法容纳在内存中。这也更友好于HDD,因为它允许其他进程在每个块之间访问它,而不是锁定它。

当通过FileReader读取文件时,你要求浏览器将整个文件读取到内存中,然后在通过XHR发送时使用内存中的数据。因此,你受限于可用内存,导致内存膨胀而没有任何好处,并且甚至要求CPU在此处工作,尽管数据几乎可以从磁盘直接传输到网络卡。


关于formdata.append(file); xhr.send(formdata);xhr.send(file)之间的区别,基本上只有请求头。前者会将请求封装为multipart/form-data enctype请求,而后者会按原样发送。
因此,在接收端你需要以不同的方式处理两个请求。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接