Web content streaming requires sending partial files between a server and a client, most often a web browser. This is a strict requirement for controlling audio playback using an HTML audio tag. While a simple HTTP 200 response containing the whole file will work for most use cases, it will not allow proper playback control, as is to be expected of a respectable music streaming app.
Request
First, the browser requests a partial file by including the Range
header, which encodes the position in bytes. The first word refers to the allowed range type, bytes
in our case.
bytes=<start_offset>-<end_offset>
Response
Next, the server should reply that :
- it accepts file ranges, using the
Accept-Ranges: bytes
header; - it is sending an incomplete file, using the
206
HTTP status code, containing a specific number of bytes with theContent-Length
header; - and that it is sending the requested byte range, in the
Content-Range
header.
The Content-Range
header should contain the first byte index, the last, and the total file size.
Content-Range: bytes <start>-<end>/<total>
Note that the last fragment’s “end” offset should be exactly one less than the total file size.
Example
Below is a quick and dirty example for sending a partial file in python.
if request.headers['HTTP_RANGE']: total_size = os.path.getsize(filename) http_range = request.headers['HTTP_RANGE'] start = int(http_range.split("=")[1].split("-")[0]) end = start + 2000000 if http_range.split("-")[1] == '' else int(http_range.split("-")[1]) if end > total_size: end = total_size - 1 with open(filename, 'rb') as f: f.seek(start) body = f.read(end - start) return Response(206, {"Content-Type": "application/octet-stream", "Accept-Ranges": "bytes", "Content-Range": "bytes {}-{}/{}".format(start, end, total_size)}, body)