http://stackoverflow.com/questions/3303029/http-range-header

***************************

58 down vote favorite

25
 

I was reading http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35 and trying to figure out how to continue a file download.

For example, suppose a file is of length 100 bytes and I have all the 100 bytes. However, I don't know what the expected file size should be, so I ask for the file and specify a Range header that looks like this:

Range: bytes=100-

Is this a valid Range request?

asked Jul 21 '10 at 19:28
dhruvbird

2,59622432
 
5  
Erm, the example under it cites 'bytes=9500-' as valid, so.... – Wrikken Jul 21 '10 at 19:36
1  
The most current ref is RFC7233 -- httpwg.github.io/specs/rfc7233.html – Mark Nottingham Apr 16 '15 at 21:24

3 Answers

up vote 41 down vote accepted

It's a syntactically valid request, but not a satisfiable request. If you look further in that section you see:

If a syntactically valid byte-range-set includes at least one byte- range-spec whose first-byte-pos is less than the current length of the entity-body, or at least one suffix-byte-range-spec with a non- zero suffix-length, then the byte-range-set is satisfiable. Otherwise, the byte-range-set is unsatisfiable. If the byte-range-set is unsatisfiable, the server SHOULD return a response with a status of 416 (Requested range not satisfiable). Otherwise, the server SHOULD return a response with a status of 206 (Partial Content) containing the satisfiable ranges of the entity-body.

So I think in your example, the server should return a 416 since it's not a valid byte range for that file.

answered Jul 21 '10 at 20:10
Marc Novakowski

31.4k75059
 
    
So is there any way a client can resume a download without making a HEAD call to first figure out the content length and then do the math and fetch the actual content? I mean some sort of open addressing like "give me all bytes after such and such byte..." – dhruvbird Jul 21 '10 at 20:18
5  
The client will already know if it has all of the data from the original request - it should have either received a Content-Length header in the original response, or if it was chunked encoding it will have received a zero-length chunk to indicate the response was complete. If you haven't saved off this state and just have a chunk of bytes on disk, then yes you'll have to either do a HEAD request or use the Range header to ask for a byte range, and if you get back a 416 response you know you have all the bytes. – Marc Novakowski Jul 21 '10 at 20:41
    
I think Expect-Continue lets you do streaming chunks more or less like desired? – MJB Jun 10 '11 at 3:37
    
@MarcNovakowski Actually, consider the case of wget and using the -c flag. Since wget doesn't maintain any metadata about the file being complete, suppose the size of the file on disk is 99 bytes. wget will request the byte range "100-", and I feel that the server should respond with a 0 length response since the request is just 1 past the end of the file. – dhruvbird Jan 17 '14 at 3:06

Did you find this question interesting? Try our newsletter

Sign up for our newsletter and get our top new questions delivered to your inbox (see an example).

 

As Wrikken suggested, it's a valid request. It's also quite common when the client is requesting media or resuming a download.

A client will often test to see if the server handles ranged requests other than just looking for an Accept-Ranges response. Chrome always sends a Range: bytes=0- with its first GET request for a video, so it's something you can't dismiss.

Whenever a client includes Range: in its request, even if it's malformed, it's expecting a partial content (206) response. When you seek forward during HTML5 video playback, the browser only requests the starting point. For example:

Range: bytes=3744-

So, in order for the client to play video properly, your server must be able to handle these incomplete range requests.

You can handle the type of 'range' you specified in your question in two ways:

First, You could reply with the requested starting point given in the response, then the total length of the file minus one (the requested byte range is zero-indexed). For example:

Request:

GET /BigBuckBunny_320x180.mp4
Range: bytes=100-

Response:

206 Partial Content
Content-Type: video/mp4
Content-Length: 64656927
Accept-Ranges: bytes
Content-Range: bytes 100-64656926/64656927

Second, you could reply with the starting point given in the request and an open-ended file length (size). This is for webcasts or other media where the total length is unknown. For example:

Request:

GET /BigBuckBunny_320x180.mp4
Range: bytes=100-

Response:

206 Partial Content
Content-Type: video/mp4
Content-Length: 64656927
Accept-Ranges: bytes
Content-Range: bytes 100-64656926/*

Tips:

You must always respond with the content length included with the range. If the range is complete, with start to end, then the content length is simply the difference:

Request: Range: bytes=500-1000

Response: Content-Range: bytes 500-1000/123456

Remember that the range is zero-indexed, so Range: bytes=0-999 is actually requesting 1000 bytes, not 999, so respond with something like:

Content-Length: 1000
Content-Range: bytes 0-999/123456

Or:

Content-Length: 1000
Content-Range: bytes 0-999/*

But, avoid the latter method if possible because some media players try to figure out the duration from the file size. If your request is for media content, which is my hunch, then you should include its duration in the response. This is done with the following format:

X-Content-Duration: 63.23

This must be a floating point. Unlike Content-Length, this value doesn't have to be accurate. It's used to help the player seek around the video. If you are streaming a webcast and only have a general idea of how long it will be, it's better to include your estimated duration rather than ignore it altogether. So, for a two-hour webcast, you could include something like:

X-Content-Duration: 7200.00

With some media types, such as webm, you must also include the content-type, such as:

Content-Type: video/webm

All of these are necessary for the media to play properly, especially in HTML5. If you don't give a duration, the player may try to figure out the duration (to allow for seeking) from its file size, but this won't be accurate. This is fine, and necessary for webcasts or live streaming, but not ideal for playback of video files. You can extract the duration using software like FFMPEG and save it in a database or even the filename.

X-Content-Duration is being phased out in favor of Content-Duration, so I'd include that too. A basic, response to a "0-" request would include at least the following:

HTTP/1.1 206 Partial Content
Date: Sun, 08 May 2013 06:37:54 GMT
Server: Apache/2.0.52 (Red Hat)
Accept-Ranges: bytes
Content-Length: 3980
Content-Range: bytes 0-3979/3980
Content-Type: video/webm
X-Content-Duration: 2054.53
Content-Duration: 2054.53

One more point: Chrome always starts its first video request with the following:

Range: bytes=0-

Some servers will send a regular 200 response as a reply, which it accepts (but with limited playback options), but try to send a 206 instead to show than your server handles ranges. RFC 2616 says it's acceptable to ignore range headers.

answered Sep 11 '13 at 15:21
Victor Stoddard

1,52811115
 
1  
Who is working on the definition of Content-Duration? Link? – Julian Reschke Sep 11 '13 at 15:33
    
What do you do if the content is a live video stream that does not have a fixed duration? – Joel Barsotti Feb 16 '14 at 21:12
    
@Joel, you need to reply with a duration even if you don't know it. In that case, just try 0.0. For the client, the duration doesn't matter anyway since you can't usually scan a live stream. If the 0.0 doesn't work, just try something really high like 1000000.00. – Victor Stoddard Apr 2 '14 at 1:55
    
@VictorStoddard can chunked streaming be applied to regular file download where no Range header is present in client request? How should server respond in that case? – gkiko Sep 23 '15 at 10:32
    
@gkiko There isn't much difference other than using the Transfer-Encoding header instead of Content-Length in Chunked Transfer Encoding. Chunks can come from a single file and the server can set the chunk size. The client should buffer and piece together the chunks as they're received. Alternatively, HTTP Streaming uses prerecorded segments of a media file, where they are saved on the server as individual parts (ts files). These segments are served using regular HTTP file GET requests obtained from an index file. I've found segmenting to be tricky but that was years ago. – Victor Stoddard Sep 24 '15 at 2:20

Contrary to Mark Novakowski answer, which for some reason has been upvoted by many, yes, it is a valid and satisfiable request.

In fact the standard, as Wrikken pointed out, makes just such an example. In practice, Firefox responds to such requests as expected (with a 206 code), and this is exactly what I use to implement progressive download, that is, only get the tail of a long log file which grows in real time with polling.

answered Jan 16 '14 at 14:14
 
1  
Please read Marc Novakowki's answer again. "satisfiable" has a particular meaning in the RFC, which he quoted. This request is not satisfiable because the requested bytes are beyond the length of the file. – Scott Lamb Nov 9 '15 at 4:49
 

HTTP Range header的更多相关文章

  1. PHP header() http各种状态码大全查询

    PHP header()the function declaration: void header ( string string [, bool replace [, int http_respon ...

  2. 数据流分段下载(Http之 Range)

    public FileStreamResult StreamUploadedSongs(int id) { byte[] song = db.UploadedSongs.Where(x => x ...

  3. squid对http range的处理以及range_offset_limit

    range_offset_limit A range request comes from a client that wants only some subset of an HTTP respon ...

  4. (实例篇)PHP实现HTTP断点续传的方法

    PHP实现HTTP断点续传的方法. <?php /** * PHP-HTTP断点续传实现 * @param string $path: 文件所在路径 * @param string $file: ...

  5. HTTP请求应答服务——HTTP Request & Response Service

    服务站点:https://httpbin.org/ Freely hosted in HTTP, HTTPS & EU flavors by Runscope DESCRIPTION Test ...

  6. HTTP超文本传输协议-HTTP/1.1中文版

    摘要 超文本传输协议(HTTP)是一种为分布式,合作式,多媒体信息系统服务,面向应用层的协议.它是一种通用的,不分状态(stateless)的协议,除了诸如名称服务和分布对象管理系统之类的超文本用途外 ...

  7. http-code 未译

    1xx Informational Request received, continuing process. This class of status code indicates a provis ...

  8. Apache Mod/Filter Development

    catalog . 引言 . windows下开发apache模块 . mod进阶: 接收客户端数据的 echo 模块 . mod进阶: 可配置的 echo 模块 . mod进阶: 过滤器 0. 引言 ...

  9. php 下载文件的函数

    通过函数完成下载文件的PHP功能代码 function download($url, $filename) { // 获得文件大小, 防止超过2G的文件, 用sprintf来读 $filesize = ...

随机推荐

  1. [转]使用VS2010的Database 项目模板统一管理数据库对象

    本文转自:http://www.cnblogs.com/shanyou/archive/2010/05/08/1730810.html Visual Studio 2010 有一个数据库项目模板:Vi ...

  2. PAAS云服务平台

    云计算是一种可以方便.按需从网络訪问的.可配置的.共享的资源池(如网络.server.存储.应用程序和服务)模型,且仅仅需最少的管理(服务提供方交互)就可以高速供应和公布该模型. 云计算平台的核心部分 ...

  3. 新闻焦点切换flash应用

    pixviewer.zip <!-- pixviewer.swf使用--> <script language="javascript" type="te ...

  4. linux内核及其模块的查询,加载,卸载 lsusb等

    http://blog.sina.com.cn/s/blog_53e81e2a0100zkxi.html 1,/sbin/update-modules文件,他是一个linux通用的模块管理脚本程序. ...

  5. vue2.0快速构建项目

    准备工作:已经安装了nodejs,已经安装了vue-cli $ mkdir gankbook $ cd gankbook $ vue init webpack-simple 按照需要写好信息,这将会写 ...

  6. 使用Loadrunner进行文件的上传和下载

    最近使用loadrunner中需要录制文件的上传和下载,上传功能模块利用录制可以直接实现,下载无法实现,在网上找到了一段代码,自己动手试验了下,发现没有用 辛苦找到的,还是记录下吧 (1)LoadRu ...

  7. js实现页面跳转的两种方式

      CreateTime--2017年8月24日08:13:52Author:Marydon js实现页面跳转的两种方式 方式一: window.location.href = url 说明:我们常用 ...

  8. hibernate 多对一关联

    (转自尚学堂教学内容)   注解多对一: package com.bjsxt.hibernate; import javax.persistence.Entity; import javax.pers ...

  9. Drupal启动阶段之二:页面缓存

    页面缓存是什么意思?有些页面浏览量非常大,而且与状态无关,这类页面就可以使用页面缓存技术.在页面第一次请求完毕以后,将响应结果保存起来.下一次再请求同一页面时,就不需要从头到尾再执行一遍,只需要将第一 ...

  10. 关于DevOps你必须知道的11件事

    转自:http://www.infoq.com/cn/articles/11devops 关于作者 Gene Kim在多个角色上屡获殊荣:CTO.研究者和作家.他曾是Tripwire的创始人并担任了1 ...