Send a file with XmlHttpRequest: Streaming?
I am trying to upload big files with drag and drop. I have this piece of Javascript code:
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 url
is a string of the target url and file
is 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.
However, if the file is big enough the request is never sent. Instead, the XMLHttpRequest
object fires and error event (without any useful message). This limit is 86Mb in my environment, but it varies from machine to machine.
The javascript console of Chrome shows the message:
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.
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?
Try using the Blob.slice
method to split the Blob
up into multiple chunks, and send each one as a separate request.
Today, with chrome 31 (windows), xhr.send(file) will not read 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.
As a side note, xhr.send(file)
fits better for PUT upload, for POST more appropriate would be 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.
精彩评论