前幾天一個同事跑過來找我說,咱們在廣告素材視頻這塊想作斷點續傳,就是此次某個視頻緩存到一半,下次不用重頭開始,能夠在原來停留得位置開始繼續下載.以提供更好的用戶體驗。linux
同時說須要咱們支持吐素材地址的業務接口告訴終端最後修改時間/文件簽名(md5),用這個用來判斷我當前要下的文件有沒有變化,同時告訴終端文件的Size大小.程序員
我一細想,這個問題壓根不須要經過改變現有接口提供更多的數據來作.下面從原理實現上簡單說下:shell
關鍵點:後端
對於斷點續傳,關鍵點是兩個:緩存
1. 終端知道當前的文件和上一次加載的文件是否是內容發生了變化,若是有變化,須要從新從offset 0 的位置開始下載服務器
2. 終端記錄好上次成功下載到的offset,告訴server端,server端支持從特定的offset 開始吐數據curl
文件變化感知:工具
前置業務接口方案:url
對於關鍵點1,對於決定大部分產品的業務場景,能夠經過前置業務接口解決;這裏簡單介紹一下:spa
對於非下載工具類的產品,如視頻APP(奇藝,優酷),視頻播放前會請求相關業務的信息,主要返回片子叫什麼名字,主要演員等等一些列信息,同時會返回一個對於播放最重要的信息——播放地址。
播放地址就是咱們能夠作文章的地方,若是《太子妃第一集》這個片子更新了(被廣電要求減掉某個污的畫面),能夠後端系統讓這個業務接口吐不一樣的播放地址/一個不一樣的url參數(?ver=1.1)/位置參數(#ver1.1)。這樣純自然的URL變化能純自然的讓終端認爲不是同一個片子,而須要從新加載。
HTPP 標準ETAG方案:
沒有業務接口的下載工具類的如何解決呢?
下載工具類的沒有前置接口,可使用HTTP 的ETAG來標識是否文件已經修改。
ETAG原理:若是URL上的資源內容改變,一個新的不同的ETag就會被分配。用這種方法使用ETag即相似於指紋,而且他們可以被快速地被比較,以肯定兩個版本的資源是否相同。ETag的比較只對同一個URL有意義——不一樣URL上的資源的ETag值可能相同也可能不一樣,從他們的ETag的比較中無從推斷。
ETAG是HTTP的一個可選字段,且沒有規範他的實現;實際上業內用的比較多的就是使用MD5簽名的方式來生成(linux shell md5sum)
典型用法:
server端: Nginx >1.3.3 自帶有ETAG的module , 固然同時也能夠在業務代碼裏SetHeaders加一個ETAG字段
client端:
第一次請求時:
String etag = httpURLConnection.getHeaderField("ETag");
ETag: "b428eab9654aa7c87091e"
第二次請求(斷點續傳時):
httpURLConnection.setRequestProperty(「If-None-Match」, "b428eab9654aa7c87091e");
If-None-Match: "b428eab9654aa7c87091e"
若是ETag值匹配,這就意味着資源沒有改變,服務器便會發送回一個極短的響應,包含HTTP 「304 未修改」的狀態。304狀態告訴客戶端,它的緩存版本是最新的,並應該使用它。
然而,若是ETag的值不匹配,這就意味着資源極可能發生了變化,那麼,一個完整的響應就會被返回,包括資源的內容,就好像ETag沒有被使用。這種狀況下,客戶端能夠用新返回的資源和新的ETag替代先前的緩存版本。
續傳支持:
對於一個C/C++程序員,第一時間會得出一個系統級實現方案:
1. 客戶端傳當前的offset
2. server端seek到文件特定的offset開始讀取往http connection吐數據
不過咱們深處在一個開放方案和標準不斷完善的時代,不須要本身實現一個(這也是像我這樣的C/C++研發工程師愈來愈沒落的緣由),來看看HTTP協議是怎麼解決這個問題的:
HTTP頭Range字段:
Range : 用於客戶端到服務器端的請求,可經過該字段指定下載文件的某一段大小,及其單位。典型的格式如:
Range: bytes=0-499 下載第0-499字節範圍的內容
Range: bytes=500-999 下載第500-999字節範圍的內容
Range: bytes=-500 下載最後500字節的內容
Range: bytes=500- 下載從第500字節開始到文件結束部分的內容
來個簡單粗暴的例子
curl --header "Range: bytes=0-20000" xxx.com/memcache.pdf -o part1
curl --header "Range: bytes=20001-223651" xxx.com/memcache.pdf -o part2
cat part1 part2 >> a.pdf
衍生閱讀: