HTTP 范围请求

HTTP Range 请求要求服务器仅将 HTTP 消息的一部分发送回客户端。对于支持随机访问的客户端(如媒体播放器)、知道只需要大型文件一部分的数据工具以及允许用户暂停和恢复下载的下载管理器,范围请求非常有用。

检查服务器是否支持部分请求

如果 HTTP 响应包含 Accept-Ranges 标头,并且其值为除“none”之外的任何内容,则表示服务器支持范围请求。您可以使用 cURL 等工具发出 HEAD 请求进行手动检查。

bash
curl -I http://i.imgur.com/z4d4kWk.jpg
http
HTTP/1.1 200 OKAccept-Ranges: bytes
Content-Length: 146515

在此响应中,Accept-Ranges: bytes 表示可以使用字节作为单位来定义范围。此处,Content-Length 标头也很有用,因为它指示要检索的图像的完整大小。

如果站点省略了 Accept-Ranges 标头,则可能不支持部分请求。某些站点包含该标头,但将其显式设置为“none”以指示它们缺乏支持。

bash
curl -I https://www.youtube.com/watch?v=EwTZ2xpQwpA
http
HTTP/1.1 200 OKAccept-Ranges: none

在这种情况下,下载管理器可能会禁用其暂停按钮。

向服务器请求特定范围

如果服务器支持范围请求,则通过在 HTTP 请求中包含 Range 标头,您可以指定希望服务器返回的文档的哪一部分或哪些部分。

单部分范围

我们可以从资源中请求单个范围。同样,我们可以使用 cURL 测试请求。“-H”选项会将标头行附加到请求中,在本例中,它是请求前 1024 个字节的 Range 标头。

bash
curl http://i.imgur.com/z4d4kWk.jpg -i -H "Range: bytes=0-1023"

发出的请求如下所示

http
GET /z4d4kWk.jpg HTTP/1.1
Host: i.imgur.com
Range: bytes=0-1023

服务器使用 206 Partial Content 状态进行响应

http
HTTP/1.1 206 Partial Content
Content-Range: bytes 0-1023/146515
Content-Length: 1024
…
(binary content)

Content-Length 标头现在指示请求范围的大小(而不是图像的完整大小)。Content-Range 响应标头指示此部分消息在完整资源中的位置。

多部分范围

Range 标头还允许您在多部分文档中一次获取多个范围。范围之间用逗号分隔。

bash
curl http://www.example.com -i -H "Range: bytes=0-50, 100-150"

服务器使用 206 Partial Content 状态和 Content-Type: multipart/byteranges; boundary=3d6b6a416f9b5 标头进行响应,指示接下来是多部分字节范围。每个部分都包含其自己的 Content-TypeContent-Range 字段,并且必需的边界参数指定用于分隔每个主体部分的边界字符串。

http
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

<!DOCTYPE html>
<html lang="en-US">
<head>
    <title>Example Do
--3d6b6a416f9b5
Content-Type: text/html
Content-Range: bytes 100-150/1270

eta http-equiv="Content-type" content="text/html; c
--3d6b6a416f9b5--

条件范围请求

在恢复请求资源的更多部分时,您需要保证存储的资源自上次接收片段以来未被修改。

If-Range HTTP 请求标头使范围请求成为条件请求:如果条件满足,则将发出范围请求,并且服务器将使用相应的正文发送 206 Partial Content 响应。如果条件不满足,则将发送完整资源,并使用 200 OK 状态。此标头可以与 Last-Modified 验证器或 ETag 一起使用,但不能同时使用两者。

http
If-Range: Wed, 21 Oct 2015 07:28:00 GMT

部分请求响应

在处理范围请求时,有三个相关的状态

  • 成功的范围请求会从服务器获取 206 Partial Content 状态。
  • 超出范围的范围请求将导致 416 Requested Range Not Satisfiable 状态,这意味着没有一个范围值与资源的范围重叠。例如,每个范围的第一个字节位置都可能大于资源长度。
  • 如果不支持范围请求,则会发送 200 OK 状态,并传输整个响应正文。

与分块Transfer-Encoding 的比较

Transfer-Encoding 标头允许分块编码,这在将大量数据发送到客户端并且在完全处理请求之前不知道响应的总大小时非常有用。服务器会立即将数据发送到客户端,而无需缓冲响应或确定确切的长度,从而导致延迟减少。范围请求和分块是兼容的,可以彼此独立使用。

另请参阅