HTTP range 請求允許我們從服務器上只發送HTTP消息的一部分到客戶端。這樣的部分請求對于大型媒體、具有中斷和恢復下載進度的下載文件請求很有幫助。
在進行HTTP range 請求之前,先檢查服務器是否支持部分請求
如果請求一個資源時, HTTP響應中出現如下所示的 'Accept-Ranges', 且其值不是none, 那么服務器支持范圍請求。
curl -I http://i.imgur.com/z4d4kWk.jpg
HTTP/1.1 200 OK
...
Accept-Ranges: bytes
Content-Length: 146515
在如上響應中,Accept-Ranges: bytes 代表可以使用字節作為單位來定義請求范圍。這里的 Response Headers中的 Content-Length: 146515 則代表該資源的完整大小。
如果站點響應中未返回 Accept-Ranges 響應頭,或者其值為none,那么這意味著server不支持HTTP range請求。
我們可以對一個資源發起單個范圍請求:
curl http://i.imgur.com/z4d4kWk.jpg -i -H "Range: bytes=0-1023"
發出的請求如下:
GET /z4d4kWk.jpg HTTP/1.1 Host: i.imgur.com Range: bytes=0-1023
正常情況下 server 返回 206 部分內容響應:
HTTP/1.1 206 Partial Content Content-Range: bytes 0-1023/146515 Content-Length: 1024 ... (binary content)
這次并非檢查server是否支持range請求,故Content-Length表示的是現在請求的范圍大小,而Content-Range則表示的是這部分消息在完整資源中的位置。
curl http://www.example.com -i -H "Range: bytes=0-50, 100-150"
用逗號隔開多個范圍,即可同時請求多部分資源。
響應如下:
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
該響應有:
每個部分包含自己的Content-Type 和 Content-Range
當繼續請求更多資源時,你需要確保被存儲的資源在上一幀收到后沒有被改變。
If-Range HTTP請求創建了一個帶條件的range HTTP請求,如果條件得到滿足,range請求將會被發出,server 發回帶有適當正文的206 partial content 應答,如果條件不滿足則返回完整資源,并顯示200 OK狀態。這個頭可以與Last-Modified 驗證程序,或者與 ETag 一起使用。
If-Range: Wed, 21 Oct 2015 07:28:00 GMT
在處理HTTP Range 請求時,有三個相關的狀態:
Transfer-Encoding 請求頭允許分塊編碼,這在服務器給客戶端發送大量的數據,且響應總大小直到請求結束才能確定時很有用,如果服務器直接發送數據給客戶端而不緩存響應,或者確定具體響應大小的話,會產生延遲。HTTP Range 請求和分塊是兼容的,一起用或者不一起用均可。
天這篇文章和大家聊一聊如何做到只請求資源的一部分,這里需要用到幾個http頭——range、if-range、content-range、accept-range。
Range主要用來設置獲取數據的范圍,格式如下:
Range: <unit>=<range-start>-<range-end>
Range: <unit>=<range-start>-<range-end>, <range-start>-<range-end>, <range-start>-<range-end>
如: 獲取 0-10字節的數據和15到結尾的數據
Range: bytes=0-10,15-
If-Range主要用來判斷是否滿足范圍請求的條件,舉個例子,假設昨天你用迅雷下載了一部電影但是沒有下載完,今天你要接著下載,當再次下載時客戶端就需要和服務器驗證這部電影的資源內容有沒有發生變化,If-Range在這里就是做驗證使用的 。
Content-Range表示響應數據的內容范圍,語法格式如下:
Content-Range: <unit> <range-start>-<range-end>/<size>
Content-Range: <unit> <range-start>-<range-end>/*
Content-Range: <unit> */<size>
例如:
Content-Range: bytes?10-15/22
Accept-Ranges用于服務器響應,告訴瀏覽器是否支持Range,
語法:
Accept-Ranges: bytes
Accept-Ranges: none
上面介紹了幾個頭信息的概念,下面我們用代碼實現一下,大概流程如下:
圖1
我們還是以中間件的方式去實現。
圖2
如圖2,我們通過range頭獲取請求的范圍信息,如果類型合法,我們還需要處理范圍數據,處理方式和處理url的query一樣,在處理的過程中我們需要對不合法的范圍進行糾正和過濾。如果類型不合法,我們就正常返回整個內容。
對于range范圍內重疊和相鄰的區域可以做一次合并,例如:
bytes=50-55,0-10,5-10,56-60,可以合并為[{start: 0, end: 10},{start: 50, end: 60}]。
圖3
如圖3,如果range范圍無效,我們返回狀態碼416,告訴客戶端range是無效的,不滿足要求。
圖4
如圖4,如果range范圍校驗也沒問題,我們還需要通過if-range提供的信息與etag或者Last-Modified做對比(對比二選一)。
如果不滿足if-range條件,繼續走正常返回資源的邏輯,如果滿足那就開始返回部分資源。
圖5
如圖5,設置了狀態為206,這是http標識部分內容返回的狀態,另外還設置了accept-range和content-type。此處我們使用stream對內容進行分片,這里只返回了一段范圍的內容。
對于多段請求,也是可以實現的,如下:
圖6
需要把content-type設置成multipart/byteranges; boundary=分隔符,這樣的話就可以分片下載了。
這篇文章主要介紹了range頭相關的使用方法,內容還是蠻多的。本文的代碼實現沒那么全,主要講了一下原理及流程,小伙伴們如果需要使用可以再打磨一下。
Hypertext Transfer Protocol,超文本傳輸協議,和HTML(Hypertext MarkupLanguage 超文本標記語言)一起誕生的,用于在網絡上請求和傳輸HTML內容。
超文本,也就是擴展文本,指的是HTML中可以有鏈向別的文本的鏈接(hyperlink)。
瀏覽器:
用戶輸入地址回車或點擊鏈接->瀏覽器拼裝HTTP報文并發送請求給服務器->服務器處理請求后發送響應報文給瀏覽器->瀏覽器解析響應報文并使用渲染引擎顯示到界面
手機App:
用戶點擊或界面自動觸發聯網需求->Android代碼調用拼裝HTTP報文并發送請求到服務器->服務器處理請求后發送響應報文給手機->Android代碼處理響應報文并作出相應處理(如儲存數據、加工數據、顯示數據到界面)
URL格式
三部分:協議類型、服務器地址(和端口號)、路徑(Path)
協議類型://服務器地址[:端口號]路徑
例如:http://toutiao.com/users?gender=male
報文格式
請求報文
響應報文
GET
對應Android Retrofit的代碼
POST
對應Retrofit的代碼:
PUT
對應Retrofit的代碼:
DELETE
HEAD
Status Code狀態碼
三位數字,用戶對響應結果做出類型化描述(如獲取成功,內容未找到)。
作用:HTTP消息的metadata。
Host
目標主機。注意:不是在網絡上用于尋址的,而是在目標服務器上用于定位子服務器的。
Content-Type
指定Body的類型,主要有四類:
請求Web頁面是返回響應的類型,Body中返回html文本。格式如下:
Web頁面純文本表單的提交方式。
格式如下:
對應Retrofit的代碼
Web頁面含有二進制文件時的提交方式。
格式如下:
對應Retrofit的代碼:
單項內容(文本或非文本都可以),用于Web Api的響應或者POST/PUT的請求
請求中提交JSON
對應Retrofit的代碼
響應中返回JSON
請求中提交二進制內容
對應Retrofit的代碼
相應中返回二進制內容
指定Body的長度(字節)。
Transfer:chunked(分塊傳輸編碼Chunked Transfer Encoding)
用于當響應發起時,內容長度還沒能確定的情況下。和Content-Length不同時使用。用途是盡早給出響應,減少用戶等待。
格式:
指定重定向的目標URL
用戶代理,即是誰實際發送請求、接受響應的,例如手機瀏覽器、某款手機App。
按范圍取數據
Accept-Range:bytes響應報文中出現,表示服務器支持按字節來取范圍數據
Range:bytes=<start>-<end>請求報文中出現,表示要取哪段數據
Content-Range:<start>-<end>/total響應報文中出現,表示發送的是哪段數據
作用:斷點續傳、多線程下載。
作用:在客戶端或中間網絡節點緩存數據,降低從服務器數據的頻率,以提高網絡性能。
REST的定義眾說紛紜,沒有統一答案。
個人認為:REST HTTP即正確使用HTTP。包括:
1.【單選題】用戶在瀏覽器地址欄輸入地址后回車,一段時間后瀏覽器顯示出頁面,這背后發生了什么?
A. 瀏覽器拼裝 HTTP 報文并向服務器請求 -> 服務器處理請求并返回響應報文 -> 瀏覽器接收到響應報文后處理并使用渲染引擎來渲染出界面
B. 瀏覽器把地址欄的 URL 發送給服務器 -> 服務器把 URL 對對應的頁面圖片文件發回給瀏覽器 -> 瀏覽器接收到圖片后顯示出來
2.【單選題】一個 URL 如 http://api.qq.com/user/1 中,對于「HTTP 組裝報文」來說可以拆成哪幾部分
A. ① 【http:】-> 協議類型 ② 【//api.qq.com/user/1】-> 路徑
B. ① 【http:】-> 協議類型 ② 【//api.qq.com】-> 服務器地址 ③ 【/user/1】-> 路徑
C. ① 【http:】-> 協議類型 ② 【//api.qq.com/user/】-> 路徑 ③ 【1】-> 文件名
3.【單選題】HTTP 的請求報文分為哪幾部分?
A. 請求行、path、Headers、Body
B. 請求行、Headers、Body
C. 請求行、方法、Host、Body
4.【單選題】請求行由哪三部分組成?
A. method、path、HTTP 版本
B. method、path、Host
C. method、服務器地址、path
5.【單選題】HTTP 的響應報文分為哪幾部分?
A. 響應頭、響應碼、響應信息
B. 狀態行、響應頭、Headers、Body
C. 狀態行、Headers、Body
6.【單選題】響應報文的狀態行由哪三部分組成?
A. HTTP 版本、API 版本、狀態碼
B. HTTP 版本、狀態碼、狀態信息
C. HTTP 版本、Body 類型、狀態碼
7.【多選題】以下哪幾項符合 GET 方法?
A. 用于獲取資源A
B. 用于增加或修改資源
C. 僅用于修改資源
D. 用于刪除資源
E. 冪等(即反復調用多次時會得到相同的結果)E. 冪等(即反復調用多次時會得到相同的結果)
F. 請求報文中包含 BodyF. 請求報文中包含 Body
8.【多選題】以下哪幾項符合 POST 方法?
A. 用于獲取資源A. 用于獲取資源
B. 用于增加或修改資源B. 用于增加或修改資源
C. 僅用于修改資源C. 僅用于修改資源
D. 用于刪除資源D. 用于刪除資源
E. 冪等(即反復調用多次時會得到相同的結果)E. 冪等(即反復調用多次時會得到相同的結果)
F. 請求報文中包含 BodyF. 請求報文中包含 Body
9.【多選題】以下哪幾項符合 PUT 方法?
A. 用于獲取資源A. 用于獲取資源
B. 用于增加或修改資源B. 用于增加或修改資源
C. 僅用于修改資源C. 僅用于修改資源
D. 用于刪除資源D. 用于刪除資源
E. 冪等(即反復調用多次時會得到相同的結果)E. 冪等(即反復調用多次時會得到相同的結果)
F. 請求報文中包含 BodyF. 請求報文中包含 Body
10.【多選題】以下哪幾項符合 DELETE 方法?
A. 用于獲取資源A. 用于獲取資源
B. 用于增加或修改資源B. 用于增加或修改資源
C. 僅用于修改資源C. 僅用于修改資源
D. 用于刪除資源D. 用于刪除資源
E. 冪等(即反復調用多次時會得到相同的結果)E. 冪等(即反復調用多次時會得到相同的結果)
F. 請求報文中包含 BodyF. 請求報文中包含 Body
11.【單選題】Host 這個 Header 的作用是?
A. 在網絡上尋址目標主機的 IP,并在找到目標主機后確認主機域名和端口
B. 僅用于尋址目標主機的 IP
C. 僅用于找到目標主機后確認主機域名和端口
12.【單選題】Content-Type 為 x-www-form-urlencoded 時,請求報文中 Body 的格式為以下哪種形式?
A. Encoded URL,即 name1=value1&name2=value2 的形式
B. 分多個部分傳輸每部分內容的形式,使用 boundary 對它們進行分隔
C. JSON 形式,如 {"name1":value1,"name2":value2}
13.【單選題】Content-Type 為 multipart/form-data 時,請求報文中 Body 的格式為以下哪種形式?
A. Encoded URL,即 name1=value1&name2=value2 的形式
B. 分多個部分傳輸每部分內容的形式,使用 boundary 對它們進行分隔
C. JSON 形式,如 {"name1":value1,"name2":value2}
14.【單選題】Content-Type 為 application/json 時,請求報文中 Body 的格式為以下哪種形式?
A. Encoded URL,即 name1=value1&name2=value2 的形式
B. 分多個部分傳輸每部分內容的形式,使用 boundary 對它們進行分隔
C. JSON 形式,如 {"name1":value1,"name2":value2}
答案:ABBACBABBDAABCB
*請認真填寫需求信息,我們會在24小時內與您取得聯系。