HTTP 請求頭 Range
請求資源的部分內容(不包括響應頭的大小),單位是byte,即字節,從0開始.
如果服務器能夠正常響應的話,服務器會返回 206 Partial Content 的狀態碼及說明.
如果不能處理這種Range的話,就會返回整個資源以及響應狀態碼為 200 OK .(這個要注意,要分段下載時,要先判斷這個)
比如:類似下面的
➜ /tmp curl -H "Range: bytes=0-10" http://127.0.0.1:8180/bg-upper.png -v * Hostname was NOT found in DNS cache * Trying 127.0.0.1... * Connected to 127.0.0.1 (127.0.0.1) port 8180 (#0) > GET /bg-upper.png HTTP/1.1 > User-Agent: curl/7.35.0 > Host: 127.0.0.1:8180 > Accept: */* > Range: bytes=0-10 > < HTTP/1.1 206 Partial Content * Server Apache-Coyote/1.1 is not blacklisted < Server: Apache-Coyote/1.1 < Accept-Ranges: bytes < ETag: W/"3103-1435633968000" < Last-Modified: Tue, 30 Jun 2015 03:12:48 GMT < Content-Range: bytes 0-10/3103 < Content-Type: image/png < Content-Length: 11 < Date: Tue, 29 Dec 2015 09:18:36 GMT < �PNG * Connection #0 to host 127.0.0.1 left intact ➜
響應頭就是 HTTP/1.1 206 Partial Content
Range 請求頭格式
Range: bytes=start-end
例如:
Range: bytes=10- :第10個字節及最后個字節的數據
Range: bytes=40-100 :第40個字節到第100個字節之間的數據.
注意,這個表示[start,end],即是包含請求頭的start及end字節的,所以,下一個請求,應該是上一個請求的[end+1, nextEnd]
響應頭
Content-Range
Content-Range: bytes 0-10/3103
這個表示,服務器響應了前(0-10)個字節的數據,該資源一共有(3103)個字節大小。
Content-Type
Content-Type: image/png
表示這個資源的類型
Content-Length
Content-Length: 11
表示這次服務器響應了11個字節的數據(0-10)
Last-Modified
Last-Modified: Tue, 30 Jun 2015 03:12:48 GMT
表示資源最近修改的時間(分段下載時要注意這個東西,因為如果修改了,分段下載可能就要重新下載了)
ETag
ETag: W/"3103-1435633968000"
這個響應頭表示資源版本的標識符,通常是消息摘要(類似MD5一樣)(分段下載時要注意這個東西,或者緩存控制也要注意這個東西)
注意,每種服務器對生成ETag的算法不同,這個要特別注意 如果使用分布式緩存,要特別要保證每台服務器生成的ETag算法是一致的.
緩存的過期,要同時結合(ETag + Last-Modified)這兩個響應頭來判斷.
強ETag
只要實體發生任何改變,都會改變ETag值.如:
ETag: "1234234234"
弱ETag
它在前面會有個 W/ ,如:
ETag: W/"12342423"
分段下載
利用這個特點,我們可以使用分段下載(多線程下載,分布式下載)
思想:先請求一個 HEAD 方法的請求,獲取總文件大小:
HEAD 請求
➜ /tmp curl -X HEAD http://127.0.0.1:8180/bg-upper.png -v * Hostname was NOT found in DNS cache * Trying 127.0.0.1... * Connected to 127.0.0.1 (127.0.0.1) port 8180 (#0) > HEAD /bg-upper.png HTTP/1.1 > User-Agent: curl/7.35.0 > Host: 127.0.0.1:8180 > Accept: */* > < HTTP/1.1 200 OK * Server Apache-Coyote/1.1 is not blacklisted < Server: Apache-Coyote/1.1 < Accept-Ranges: bytes < ETag: W/"3103-1435633968000" < Last-Modified: Tue, 30 Jun 2015 03:12:48 GMT < Content-Type: image/png < Content-Length: 3103 < Date: Tue, 29 Dec 2015 10:16:16 GMT < * transfer closed with 3103 bytes remaining to read * Closing connection 0 curl: (18) transfer closed with 3103 bytes remaining to read ➜ /tmp
那個響應頭的 Content-Length 就是總字節大小了(3103)字節.
多線程下載
假設分2條線程
線程1 下載
3103 / 2 = 1551 ➜ /tmp curl -H "Range: bytes=0-1551" http://127.0.0.1:8180/bg-upper.png -v -o 0-1151.png * Hostname was NOT found in DNS cache * Trying 127.0.0.1... % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to 127.0.0.1 (127.0.0.1) port 8180 (#0) > GET /bg-upper.png HTTP/1.1 > User-Agent: curl/7.35.0 > Host: 127.0.0.1:8180 > Accept: */* > Range: bytes=0-1551 > < HTTP/1.1 206 Partial Content * Server Apache-Coyote/1.1 is not blacklisted < Server: Apache-Coyote/1.1 < Accept-Ranges: bytes < ETag: W/"3103-1435633968000" < Last-Modified: Tue, 30 Jun 2015 03:12:48 GMT < Content-Range: bytes 0-1551/3103 < Content-Type: image/png < Content-Length: 1552 < Date: Tue, 29 Dec 2015 10:19:43 GMT < { [data not shown] 100 1552 100 1552 0 0 1376k 0 --:--:-- --:--:-- --:--:-- 1515k * Connection #0 to host 127.0.0.1 left intact ➜ /tmp
這樣子,線程1就下載了(0-1551)字節的數據了.
線程2 下載
➜ /tmp curl -H "Range: bytes=1552-3103" http://127.0.0.1:8180/bg-upper.png -v -o 1552-end.png * Hostname was NOT found in DNS cache * Trying 127.0.0.1... % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to 127.0.0.1 (127.0.0.1) port 8180 (#0) > GET /bg-upper.png HTTP/1.1 > User-Agent: curl/7.35.0 > Host: 127.0.0.1:8180 > Accept: */* > Range: bytes=1552 > < HTTP/1.1 416 Requested Range Not Satisfiable * Server Apache-Coyote/1.1 is not blacklisted < Server: Apache-Coyote/1.1 < Accept-Ranges: bytes < Content-Range: bytes */3103 < Content-Type: text/html;charset=utf-8 < Content-Language: en < Content-Length: 954 < Date: Tue, 29 Dec 2015 10:26:18 GMT < { [data not shown] 100 954 100 954 0 0 457k 0 --:--:-- --:--:-- --:--:-- 931k * Connection #0 to host 127.0.0.1 left intact ➜ /tmp
合並
cat 0-1151.png 1552-end.png > filename.png
這樣子就OK了.
HTTP 請求頭注意
根據HTTP規范,HTTP的消息頭部的字段名,是不區分大小寫的.
3.2. Header Fields
Each header field consists of a case-insensitive field name followed
by a colon (“:”), optional leading whitespace, the field value, and
optional trailing whitespace.
