HTTP Range

本文记录结合断点续传、多线程下载等场景了解HTTP Range的协议规范

问题场景

  • 客户端明确任务:从哪开始下载
  • 本地是否已有部分文件
  • 文件已下载部分在服务器端发生改变?
  • 使用几个线程并发下载
  • 下载文件的指定部分内容
  • 下载完毕后拼装成统一文件

HTTP Range规范(RFC7233)

允许服务器基于客户端的请求只发送响应包体的一部分给到客户端,而客户端自动将多个片断的包体组合成完整的体积更大的包体

  • 支持断点续传
  • 支持多线程下载
  • 支持视频播放器实时拖动

Accept-Range

服务器通过 Accept-Range 头部表示是否支持Range请求

Accept-Ranges = acceptable-ranges

  • Accept-Ranges: bytes 支持
  • Accept-Ranges: none 不支持

Range请求范围的单位

通过Range头部传递请求范围,”,”分割表示分两段获取,“-”表示获取范围

Range: bytes=0-499

举例

基于字节,设包体总长度为 10000

  • 第1个500字节: bytes=0-499
  • 第2个500字节:
    • bytes=500-999
    • bytes=500-600,601-999
    • bytes=500-700,601-999
  • 最后1个500字节:
    • bytes=-500
    • bytes=9500
  • 仅要第1个和最后1个字节: bytes=0-0,-1

Range条件请求

如果客户端已经得到了Range响应的一部分,并想在这部分响应未过期的情况下,获取其他部分的响应。
常与If-Unmodified-Since或者If-Match头部共同使用。

可以仅使用If-Range = entity-tag / HTTP-date。entity-tag和HTTP-date都是由服务端生成的。
也可以使用 Etag 或者 Last-Modified

  • entity-tag 实体的标示
  • HTTP-date 实体生成的时间

HTTP响应

206 Partial Content

如果只获取一段body,服务器会返回206 Partial Content,而不是200。

Content-Range 头部

显示当前片断包体在完整包体中的位置

Content-Range = byte-content-range / other-content-range

  • byte-content-range = bytes-unit SP ( byte-range-resp / unsatisfied-range )
    • byte-range-resp = byte-range “/“ ( complete-length / “*” )
      • complete-length = 1DIGIT (完整资源的大小,如果未知则用号替代)
      • byte-range = first-byte-pos “-“ last-byte-pos

举例

  • Content-Range: bytes 42-1233/1234
  • Content-Range: bytes 42-1233/*

412 Precondition Failed

请求过一次服务器端后,响应头部会返回一个Etag,将该Etag放入if-Match头部中再次请求。
如果匹配的话就会正常返回对应范围,如果不匹配则会返回412 Precondition Failed。就不能使用之前下载那部分进行合成文件。

416 Range Not Satisfiable

请求范围不满足实际资源的大小,其中Content-Range中的complete-length显示完整响应的长度。

200 OK

服务器不支持Range请求时,则以200返回完整的响应包体

多重范围与multipart

用逗号分割范围

Range: bytes=0-50, 100-150

响应

头部响应为multipart/byteranges,并且响应分隔符。与FORM响应类似,会分段标示,且每一段都有Content-Rnage

  • Content-Type:multipart/byteranges; boundary=…
投食入口