HTTP 範圍請求

HTTP Range 請求要求伺服器將資源的某些部分發送給客戶端。範圍請求對於各種客戶端都很有用,包括支援隨機訪問的媒體播放器、只需要大型檔案一部分的資料工具以及允許使用者暫停和恢復下載的下載管理器。

檢查伺服器是否支援部分請求

如果 HTTP 響應包含 Accept-Ranges 頭,並且其值不是 none,則伺服器支援範圍請求。如果響應省略了 Accept-Ranges 頭,則表示伺服器不支援部分請求。如果不支援範圍請求,應用程式可以適應這種情況;例如,下載管理器可以停用依賴範圍請求來恢復下載的暫停按鈕。

要檢查伺服器是否支援範圍請求,您可以發出一個 HEAD 請求來檢查頭資訊,而無需請求整個資源。如果您使用 curl,可以使用 -I 標誌來發出 HEAD 請求。

bash
curl -I https://i.imgur.com/z4d4kWk.jpg

這將生成以下 HTTP 請求

http
HEAD /z4d4kWk.jpg HTTP/2
Host: i.imgur.com
User-Agent: curl/8.7.1
Accept: */*

響應只包含頭資訊,不包含響應體

http
HTTP/2 200
content-type: image/jpeg
last-modified: Thu, 02 Feb 2017 11:15:53 GMT
…
accept-ranges: bytes
content-length: 146515

在此響應中,Accept-Ranges: bytes 表示“bytes”可以用作定義範圍的單位(目前沒有其他單位可用)。Content-Length 頭也很有用,因為它指示瞭如果您使用 GET 方法發出相同請求時影像的總大小。

從伺服器請求特定範圍

如果伺服器支援範圍請求,您可以透過在 HTTP 請求中包含 Range 頭來指定您希望伺服器返回文件的哪一部分(或多部分)。

單部分範圍

我們可以使用 curl 演示從資源請求單個範圍。-H 選項會將一個頭行新增到請求中,此處為請求前 1024 位元組的 Range 頭。最後一個選項是 --output -,它將允許將二進位制輸出列印到終端。

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

發出的請求如下所示

http
GET /z4d4kWk.jpg HTTP/2
Host: i.imgur.com
User-Agent: curl/8.7.1
Accept: */*
Range: bytes=0-1023

伺服器以 206 Partial Content 狀態響應

http
HTTP/2 206
content-type: image/jpeg
content-length: 1024
content-range: bytes 0-1023/146515
…

(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 頭,指示其後是一個多部分位元組範圍。邊界字串(本例中為 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 頭允許分塊編碼,這在向客戶端傳送大量資料且在請求完全處理之前不知道響應總大小時非常有用。伺服器會立即將資料傳送給客戶端,而無需緩衝響應或確定確切長度,從而提高了延遲。範圍請求和分塊相容,可以相互獨立使用,也可以結合使用。

另見