HTTP range 请求允许我们从服务器上只发送HTTP消息的一部分到客户端。这样的部分请求对于大型媒体、具有中断和恢复下载进度的下载文件请求很有帮助。
检查服务器是否支持 HTTP Range 请求
在进行HTTP range 请求之前,先检查服务器是否支持部分请求
如果请求一个资源时, HTTP响应中出现如下所示的 'Accept-Ranges', 且其值不是none, 那么服务器支持范围请求。
curl -I http://i.imgur.com/z4d4kWk.jpg
HTTP/1.1 200 OK
...
Accept-Ranges: bytes
Content-Length: 146515
在如上响应中,Accept-Ranges: bytes 代表可以使用字节作为单位来定义请求范围。这里的 Response Headers中的 Content-Length: 146515 则代表该资源的完整大小。
如果站点响应中未返回 Accept-Ranges 响应头,或者其值为none,那么这意味着server不支持HTTP range请求。
给服务器发HTTP Range请求
单范围请求
我们可以对一个资源发起单个范围请求:
curl http://i.imgur.com/z4d4kWk.jpg -i -H "Range: bytes=0-1023"
发出的请求如下:
GET /z4d4kWk.jpg HTTP/1.1 Host: i.imgur.com Range: bytes=0-1023
正常情况下 server 返回 206 部分内容响应:
HTTP/1.1 206 Partial Content Content-Range: bytes 0-1023/146515 Content-Length: 1024 ... (binary content)
这次并非检查server是否支持range请求,故Content-Length表示的是现在请求的范围大小,而Content-Range则表示的是这部分消息在完整资源中的位置。
多范围请求
curl http://www.example.com -i -H "Range: bytes=0-50, 100-150"
用逗号隔开多个范围,即可同时请求多部分资源。
响应如下:
HTTP/1.1 206 Partial Content Content-Type: multipart/byteranges; boundary=3d6b6a416f9b5 Content-Length: 282 --3d6b6a416f9b5 Content-Type: text/html Content-Range: bytes 0-50/1270
该响应有:
- 206部分响应码:
- Content-Type: multipart/byteranges;boundary=3d6b6a416f9b5——>表示遵循多部分 byterange
每个部分包含自己的Content-Type 和 Content-Range
条件范围请求
当继续请求更多资源时,你需要确保被存储的资源在上一帧收到后没有被改变。
If-Range HTTP请求创建了一个带条件的range HTTP请求,如果条件得到满足,range请求将会被发出,server 发回带有适当正文的206 partial content 应答,如果条件不满足则返回完整资源,并显示200 OK状态。这个头可以与Last-Modified 验证程序,或者与 ETag 一起使用。
If-Range: Wed, 21 Oct 2015 07:28:00 GMT
HTTP Range 请求响应
在处理HTTP Range 请求时,有三个相关的状态:
- 206 Partial Content——> HTTP Range 请求成功
- 416 Requested Range Not Satisfiable status.——> HTTP Range 请求超出界限
- 200 OK——> 不支持范围请求
与分块相比
Transfer-Encoding 请求头允许分块编码,这在服务器给客户端发送大量的数据,且响应总大小直到请求结束才能确定时很有用,如果服务器直接发送数据给客户端而不缓存响应,或者确定具体响应大小的话,会产生延迟。HTTP Range 请求和分块是兼容的,一起用或者不一起用均可。
断点续传
所谓断点续传,也就是要从文件已经下载的地方开始继续下载。在以前版本的 HTTP 协议是不支持断点的,HTTP/1.1 开始就支持了。一般断点下载时才用到 Range 和 Content-Range 实体头。
Range
用于请求头中,指定第一个字节的位置和最后一个字节的位置,一般格式:
Range:(unit=first byte pos)-[last byte pos]
Content-Range
用于响应头,指定整个实体中的一部分的插入位置,他也指示了整个实体的长度。在服务器向客户返回一个部分响应,它必须描述响应覆盖的范围和整个实体长度。一般格式:
Content-Range: bytes (unit first byte pos) - [last byte pos]/[entity legth]
请求下载整个文件
- GET /test.rar HTTP/1.1
- Connection: close
- Host: 116.1.219.219
- Range: bytes=0-801 //一般请求下载整个文件是bytes=0- 或不用这个头
一般正常回应
- HTTP/1.1 200 OK
- Content-Length: 801
- Content-Type: application/octet-stream
- Content-Range: bytes 0-800/801 //801:文件总大小
假设你要开发一个多线程下载工具,你会自然的想到把文件分割成多个部分,比如4个部分,然后创建4个线程,每个线程负责下载一个部分,如果文件大小为403个byte,那么你的分割方式可以为:0-99 (前100个字节),100-199(第二个100字节),200-299(第三个100字节),300-402(最后103个字节)。
分割完成,每个线程都明白自己的任务,比如线程3的任务是负责下载200-299这部分文件,现在的问题是:线程3发送一个什么样的请求报文,才能够保证只请求文件的200-299字节,而不会干扰其他线程的任务。这时,我们可以使用HTTP1.1的Range头。Range头域可以请求实体的一个或者多个子范围,Range的值为0表示第一个字节,也就是Range计算字节数是从0开始的:
表示头500个字节:Range: bytes=0-499
表示第二个500字节:Range: bytes=500-999
表示最后500个字节:Range: bytes=-500
表示500字节以后的范围:Range: bytes=500-
第一个和最后一个字节:Range: bytes=0-0,-1
同时指定几个范围:Range: bytes=500-600,601-999
所以,线程3发送的请求报文必须有这一行:
Range: bytes=200-299
服务器接收到线程3的请求报文,发现这是一个带有Range头的GET请求,如果一切正常,服务器的响应报文会有下面这行:
HTTP/1.1 206 OK
表示处理请求成功,响应报文还有这一行
Content-Range: bytes 200-299/403
斜杠后面的403表示文件的大小,通常Content-Range的用法为: . The first 500 bytes:
Content-Range: bytes 0-499/1234
. The second 500 bytes: Content-Range: bytes 500-999/1234 . All except for the first 500 bytes: Content-Range: bytes 500-1233/1234 . The last 500 bytes: Content-Range: bytes 734-1233/1234
Comments 1 条评论
博客作者 zoritoler imol
Attractive component to content. I simply stumbled upon your web site and in accession capital to assert that I get actually loved account your weblog posts. Any way I’ll be subscribing for your feeds and even I achievement you access consistently fast.