HTTP斷點續傳原理

作爲一名程序媛我也想快點進步,希望慢慢積累吧。給自己加加油。

1. 斷點續傳的必要性

大部分下載類的app,都會遇到網絡不好的情況,如果下載到最後一步卻下載失敗了,是不是會讓人很頭疼。如果能重試下載從上次下載的文件位置繼續下載,就顯得很必要了。關乎用戶體驗問題。非常 非常重要!!!!!😂

2.瞭解斷點續傳之前,瞭解下http協議。

HTTP(Hyper Text Transfer Protocol)協議是用於從萬維網(www)服務器傳輸超文本到本地瀏覽器的傳送協議。它是基於TCP/IP協議來傳遞數據的。

HTTP請求由三部分組成:狀態行、請求頭、請求體。

先看一下客戶端請求頭的一個例子:

GET /home.html HTTP/1.1
Host: developer.mozilla.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101 Firefox/50.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://developer.mozilla.org/testpage.html
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Range:bytes:500-900
Cache-Control: max-age=0

這裏不詳細展開,我們只討論和斷點續傳有關的幾個請求頭屬性。

1.Range: 只請求實體的一部分。比如:Range:bytes:500-900
2.Etag:請求實體的唯一標識符。(可以是文件md5) 比如:ETag: “737060cd8c284d8af7ad3082f209582d”
3.Last-Modified:最後資源的更改時間。用於服務器響應頭 。如: Last-Modified: Tue, 15 Nov 2010 12:45:26 GMT
4.If-Range:如果實體未改變,服務器發送客戶端丟失的部分,否則發送整個實體。參數也爲Etag。 例子:If-Range: “737060cd8c284d8af7ad3082f209582d”
5.Content-Range:用於服務器響應頭。記錄服務器返回數據的範圍及文件總大小。如:Content-Range: bytes 0-499/22400
6.If-Modified-Since:如果請求的部分在指定時間之後被修改則請求成功,未被修改則返回304代碼。 如:

If-Modified-Since: Sat, 29 Oct 2010 19:43:31 GMT

有的同學可能分不清楚是客戶端的請求頭還是服務器端的響應頭,👇下面理一下:

HTTP Request Header
Range
If-Range
If-Modified-since
HTTP Response Header
Last-Modified
Content-Range
Etag

有了這個初步瞭解之後再說下他們的關係。
舉個例子客戶端A 要從服務器端B下載文件,假設服務器B支持斷點續傳。

請求下載文件
客戶端A
服務器端B

1、客戶端第一次請求需要帶上請求頭 Range: bytes=0- ,如果不帶默認也是表示第一次請求完整文件。
2、服務器B響應頭可能包含如下屬性:

HTTP/1.1 206 Partial Content
Content-Range: bytes 0-499/22400
Last-Modified: Tue, 15 Nov 2010 12:45:26 GMT
ETag:737060cd8c284d8af7ad3082f209582d” 由服務器端生產

表示目前服務器返回了0到499bytes的數據,文件大小是22400bytes。並告訴客戶端A這個文件的最後更改日期是Tue, 15 Nov 2010 12:45:26 GMT,它的唯一標識符是“737060cd8c284d8af7ad3082f209582d”,可能是文件的MD5值,也可能是其他標識符,由服務器端來定。

對於含由Range請求頭的http數據,如果服務器能正常處理的話會返回:HTTP/1.1 206 Partial Content,如果不能處理Range也就是不支持斷點續傳的話,就會返回:HTTP/1.1 200 OK,還有一種超過資源大小範圍的請求會返回416,它的意思是“Range Not Satisfiable”,
3、請求文件下載過程網絡斷開或者服務器掛掉,文件假如下載了20000bytes。還差2400bytes。這個時候放棄多可惜😭。
4、我們需要再次請求恢復下載。這次請求帶上了一些請求頭可讓服務器B知道我們請求的文件從什麼位置開始下載的。那麼問題來了。

首先我們要確定這個URL對應的文件在服務器端沒有變化。我們就用到了第2步服務器B返回給我們的響應頭裏的Last-ModifiedEtagLast-Modified代表初次下載時文件的更新時間,Etag代表文件的唯一標識符。

有的同學可能會問,我們有Last-Modified就夠了,能判斷文件是否修改了,還要Etag幹嘛呢?如果服務器B的文件修改很頻繁,可能是毫秒級別的,那這個Last-Modified就起不了作用了,所以Etag應運而生。

那我們恢復下載怎麼把這兩個屬性值傳回去呢,就用到了我們的If-Range。它就是用來判斷服務器端文件是否發生變化的。

If-Range: Etag | HTTP-Date

它可以填寫ETag值或者Last-modified 的值。

If-Range:737060cd8c284d8af7ad3082f209582d” 
If-Range: Tue, 15 Nov 2010 12:45:26 GMT

比如我們用:

If-Range: “737060cd8c284d8af7ad3082f209582d” 
Range: bytes=20000-  表示我們這次請求是從第20001個bytes的位置到文件結束部分的內容。

其中要知道If-RangeRange是配套使用的,如果沒有Range,那麼If-Range也沒有意義。如果只有Range,那麼返回的數據就是Range中指定的位置,至於數據是否正確就不保證了。
If-Range相當於條件,如果條件成立,也就是If-Range裏的Etag和服務器B端文件的Etag一致,服務器B就會返回狀態碼是206 Partial的響應,和指定位置的響應數據。如果不滿足條件,也就是文件發生了變動,那就返回狀態碼200 OK的響應,同時返回文件起始位置的數據。返回此時文件的Etag 或者Last-Modified

梳理了一下斷點續傳的知識,想想我們項目中視頻下載的時候有用到。另外手機如果作爲server端要支持斷點續傳的話也是需要處理Range和If-Range的,Client端做好斷點續傳的,server端也要支持才行。

如果閱讀過程有發現問題請指正,大家一起進步。謝謝。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章