Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XMLHttpRequest 206 Partial Content

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?

like image 645
jamesshuang Avatar asked Mar 22 '13 02:03

jamesshuang


People also ask

Is HTTP 206 an error?

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.

What is partial content?

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.

What is partial HTTP 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.

What is Http_range?

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.


2 Answers

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
like image 63
kay Avatar answered Sep 22 '22 10:09

kay


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!

like image 22
jamesshuang Avatar answered Sep 25 '22 10:09

jamesshuang