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

What is the difference between file upload using FileReader and FormData?

我可以通过两种方式使用 Ajax (XHR2) 上传文件。首先,我可以将文件内容读取为数组缓冲区或二进制字符串,然后使用 XHR send 方法简单地流式传输。例如,作为 shown here:

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 将我的文件上传为 shown here:

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 有什么优势吗?一个比另一个更高效吗?

首先,您省略了第三个选项,即直接通过 xhr.send(file) 发送文件,就像您对 ArrayBuffer 所做的那样。

也就是说,首先通过 FileReader 读取内存中的文件不存在任何可能的优势。


从磁盘上的文件上传文件时,浏览器不会在内存中加载完整文件,而是通过请求它。这就是您可以上传千兆数据的方法,即使它不适合内存。这对 HDD 也更友好,因为它允许其他进程在每个块之间访问它而不是锁定它。

当通过 FileReader 读取文件时,您要求浏览器将 完整 文件读取到内存中,然后当您通过 XHR 发送它时,内存中的数据将被使用.因此,您受到可用内存的限制,无缘无故地膨胀,甚至要求 CPU 在这里工作,而数据几乎可以直接从磁盘传输到网卡。


至于formdata.append(file); xhr.send(formdata);xhr.send(file)有什么区别,基本上只有请求头。前者会将请求包装成 multipart/form-data enctype 请求,而后者会按原样发送。
所以你会在接收端以不同的方式处理这两个请求。