I would like to issue a partial content request from an XMLHttpRequest object in javascript. I'm loading a large binary file from the server, and I'd rather stream it from the server similar to how html5 video is handled.
I can use setRequestHeader to set the Range header. The Network inspector in Chrome shows that the Range header is set successfully. However, the Accept-Encoding header is set to "gzip,deflate", and Chrome will not let me set that header (from W3C standards).
Is there any way to force the server to respond with a 206 partial content from the XMLHttpRequest object only from javascript?
The HTTP Status Code 206 means that the server is delivering only part of the resource requested by the client due to a range header sent by the client. The range header is used by HTTP clients to enable resuming of interrupted downloads, or split a download into multiple simultaneous streams.
The HTTP 206 Partial Content success status response code indicates that the request has succeeded and the body contains the requested ranges of data, as described in the Range header of the request.
Partial request responsesA range request that is out of bounds will result in a 416 Requested Range Not Satisfiable status, meaning that none of the range values overlap the extent of the resource. For example, the first-byte-pos of every range might be greater than the resource length.
The Range HTTP request header indicates the part of a document that the server should return. Several parts can be requested with one Range header at once, and the server may send back these ranges in a multipart document. If the server sends back ranges, it uses the 206 Partial Content for the response.
This range-request works fine for me: http://jsfiddle.net/QFdU4/
var xhr = new XMLHttpRequest;
xhr.onreadystatechange = function () {
if (xhr.readyState != 4) {
return;
}
alert(xhr.status);
};
xhr.open('GET', 'http://fiddle.jshell.net/img/logo.png', true);
xhr.setRequestHeader('Range', 'bytes=100-200'); // the bytes (incl.) you request
xhr.send(null);
You have to make sure that the server allows range requests, though. You can test it with curl:
$ curl -v -r 100-200 http://example.com/movie.mkv > /dev/null
I think I figured out why the 206 request wasn't working. With gzip compression enabled, the range header gets ignored if the outgoing data can be gzipped.
The file I was requesting was a large binary file, which nginx interpreted as having mimetype application/octet-stream. This is one of the mimetypes that gets gzipped. If I renamed the file to have a .png filetype, the image/png mimetype is not gzipped, and hence the range request works correctly.
This is also why setting the Accept-Encoding header with curl to identity also allows the range request to work fine. However, I cannot change that header from an XHR.
Solution: Change the mimetype table on the server!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With