javascript 使用 XmlHttpRequest 发送文件:流式传输?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6454365/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 20:44:05  来源:igfitidea点击:

Send a file with XmlHttpRequest: Streaming?

javascriptuploadstreamingxmlhttprequest

提问by linepogl

I am trying to upload big files with drag and drop. I have this piece of Javascript code:

我正在尝试通过拖放上传大文件。我有这段 Javascript 代码:

xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.setRequestHeader('X-File-Name', file.name);
xhr.setRequestHeader('X-File-Size', file.size);
xhr.setRequestHeader('Content-Type', file.type);
xhr.send(file);

where urlis a string of the target url and fileis a Blob(according to http://www.w3.org/TR/XMLHttpRequest2/#the-send-method) which I have retrieved after a file drag-drop. This code works in Chrome 12, Safari 5 and Firefox 4 and sends the raw contents of the file in the body of the HTTP request.

其中url是目标 url 的字符串,file是我在文件拖放后检索Blob到的(根据http://www.w3.org/TR/XMLHttpRequest2/#the-send-method)。此代码适用于 Chrome 12、Safari 5 和 Firefox 4,并在 HTTP 请求正文中发送文件的原始内容。

However, if the file is big enough the request is never sent. Instead, the XMLHttpRequestobject fires and error event (without any useful message). This limit is 86Mb in my environment, but it varies from machine to machine.

但是,如果文件足够大,则永远不会发送请求。相反,XMLHttpRequest对象会触发和错误事件(没有任何有用的消息)。在我的环境中这个限制是 86Mb,但它因机器而异。

The javascript console of Chrome shows the message:

Chrome 的 javascript 控制台显示消息:

POST http://localhost/xfiles/xfiles.php undefined (undefined)

which has nothing to do with my code (which works perfectly with smaller files).

这与我的代码无关(它适用于较小的文件)。

It seems that the browser reads the entire file in memory and before sending it. Probably there is an out of memory exception or something like that that stops the process. In any case, there no HTTP request is sent, so it is certain that the server's limits have nothing to do with this problem.

浏览器似乎在发送之前读取了内存中的整个文件。可能是内存不足异常或类似的东西会停止进程。无论如何,没有发送HTTP请求,因此可以肯定服务器的限制与此问题无关。

Anyway, reading the entire file is a waste of resources.

无论如何,读取整个文件是一种资源浪费

Is there any method to send the file in a streaming fashion, byte by byte, without having to store it in the memory first?

是否有任何方法可以以流式方式逐字节发送文件,而不必先将其存储在内存中?

采纳答案by Na7coldwater

Try using the Blob.slicemethod to split the Blobup into multiple chunks, and send each one as a separate request.

尝试使用该Blob.slice方法将其拆分Blob为多个块,并将每个块作为单独的请求发送。

回答by Sandman4

Today, with chrome 31 (windows), xhr.send(file) will notread the whole file into memory. The fact is, I try to xhr.send 100mb file and look at task manager for chrome memory usage - it grows only slightly during 100mb file upload.

今天,使用 chrome 31 (windows), xhr.send(file)不会将整个文件读入内存。事实是,我尝试 xhr.send 100mb 文件并查看任务管理器以了解 chrome 内存使用情况 - 在 100mb 文件上传期间它仅略微增长。

As a side note, xhr.send(file)fits better for PUT upload, for POST more appropriate would be FormData:

作为旁注,xhr.send(file)更适合 PUT 上传,对于 POST 更合适的是 FormData:

  var formData = new FormData();
  formData.append("thefile", file);
  xhr.send(formData);

Using FormData however, increases upload time by some 50% - probably because of the base64 encoding.

然而,使用 FormData 会将上传时间增加约 50% - 可能是因为 base64 编码。