Range

Range

Range是在HTTP/1.1 (opens new window)中新增的一个字段,这个特性也是我们使用的迅雷等支持多线程下载以及断点下载的核心机制。首先客户端会发起一个带有Range: bytes=0-xxx的请求,如果服务端支持Range,则会在响应头中添加Accept-Ranges: bytes来表示支持Range的请求,之后客户端才可能发起带Range的请求。

GET /360_0388.jpg HTTP/1.1
Host: limit.qiufeng.com
Connection: keep-alive
...
Range: bytes=0-102399

HTTP/1.1 206 Partial Content
Server: openresty/1.13.6.2
Date: Sat, 19 Sep 2020 06:31:11 GMT
Content-Type: image/jpeg
Content-Length: 102400
....
Content-Range: bytes 0-102399/3670627

...(这里是文件流)

可以看到请求这里多出一个字段Range: bytes=0-102399 ,服务端也多出一个字段Content-Range: bytes 0-102399/3670627,以及返回的 状态码为206.服务端通过请求头中的Range: bytes=0-xxx来判断是否是进行Range处理,如果这个值存在而且有效,则只发回请求的那部分文件内容,响应的状态码变成206,表示Partial Content,并设置Content-Range。如果无效,则返回416状态码,表明Request Range Not Satisfiable。如果请求头中不带Range,那么服务端则正常响应,也不会设置Content-Range等。

Value Description
206 Partial Content
416 Range Not Satisfiable

Range格式

Range的格式为:

Range:(unit=first byte pos)-[last byte pos]

Range: 单位(如bytes)= 开始字节位置-结束字节位置

我们来举个例子,假设我们开启了多线程下载,需要把一个5000byte的文件分为4个线程进行下载。

  • Range: bytes=0-11991200个字节
  • Range: bytes=1200-2399第二个1200字节
  • Range: bytes=2400-3599第三个1200字节
  • Range: bytes=3600-5000最后的1400字节

服务器给出响应:

1个响应

  • Content-Length:1200
  • Content-Range:bytes 0-1199/5000

2个响应

  • Content-Length:1200
  • Content-Range:bytes 1200-2399/5000

3个响应

  • Content-Length:1200
  • Content-Range:bytes 2400-3599/5000

4个响应

  • Content-Length:1400
  • Content-Range:bytes 3600-5000/5000

如果每个请求都成功了,服务端返回的response头中有一个Content-Range的字段域,Content-Range用于响应头,告诉了客户端发送了多少数据,它描述了响应覆盖的范围和整个实体长度。一般格式:

Content-Range: bytes (unit first byte pos) - [last byte pos]/[entity length]Content-Range:字节 开始字节位置-结束字节位置/文件大小