作者 | 喵叔
責編 | 屠敏
我們都用過網盤,不管是例如百度網盤之類的公共網盤,還是自己搭建的私有網盤,都會或多或少的涉及到斷點續傳和秒傳。斷點續傳和秒傳大大提高了網盤上傳的效率,下面我們就來講解一下這兩種技術的具體原理和實現,這里的講解不涉及任何前后端編程語言,適合所有語言開發人員閱讀。
零、斷點續傳
這里以上傳為例,下載方式的斷點續傳類似。
簡述原理
斷點續傳說白了就是將一個文件按照一定的規則人為的分割成多個小文件,然后客戶端每次只上傳一個小文件(當然我們也可以利用多線程技術每次上傳多個小文件),服務器接收到上傳過來的小文件后根據一定的規則來組合這些小文件。如果在上傳過程中出現網絡中斷等意外情況,下次再次上傳時可以從已經上傳的部分繼續上傳,而不是重新上傳。
詳細講解
從 HTTP1.1 協議開始就已經支出獲取文件的部分內容,斷點續傳技術就是利用 HTTP1.1 協議的這個特點在 Header 里添加兩個參數來實現的。這兩個參數分別是客戶端請求時發送的 Range 和服務器返回信息時返回的 Content-Range - Range,Range 用于指定第一個字節和最后一個字節的位置,格式如下:
Range:(unit=first byte pos)-[ lastbyte pos]
Range 常用的格式有如下幾種情況:
- Range:bytes=0-1024 ,表示傳輸的是從開頭到第1024字節的內容;
- Range:bytes=1025-2048 ,表示傳輸的是從第1025到2048字節范圍的內容;
- Range:bytes=-2000 ,表示傳輸的是最后2000字節的內容;
- Range:bytes=1024- ,表示傳輸的是從第1024字節開始到文件結束部分的內容;
- Range:bytes=0-0,-1 表示傳輸的是第一個和最后一個字節 ;
- Range:bytes=1024-2048,2049-3096,3097-4096 ,表示傳輸的是多個字節范圍。
Content-Range Content-Range 用于響應帶有 Range 的請求。服務器會將 Content-Range 添加在響應的頭部,格式如下:
Content-Range:bytes(unit first byte pos)-[ lastbyte pos]/[entity length]
常見的格式內容如下:
Content-Range:bytes 2048-4096/10240
這里邊 2048-4096 表示當前發送的數據范圍, 10240 表示文件總大小。
這里我順便說一下,如果在客戶端請求報文頭中,對 Range 填入了錯誤的范圍值,服務器會返回 416 狀態碼。416 狀態碼表示服務器無法處理所請求的數據區間,常見的情況是請求的數據區間不在文件范圍之內,也就是說,Range 值,從語法上來說是沒問題的,但從語義上來說卻沒有意義。
注意:當使用斷點續傳的方式上傳下載軟件時 HTTP 響應頭將會變為:
HTTP/1.1 206Partial Content
當然光有 Range 和 Content-Range 還是不夠的,我們還要知道服務端是否支持斷點續傳,只需要從如下兩方面判斷即可:
- 判斷服務端是否只 HTTP/1.1 及以上版本,如果是則支持斷點續傳,如果不是則不支持
- 服務端返回響應的頭部是否包含 Access-Ranges ,且參數內容是 bytes 符合以上兩個條件即可判定位支持斷點續傳。
校驗
這里的校驗主要針對斷點續傳下載來說的。當服務器端的文件發生改變時,客戶端再次向服務端發送斷點續傳請求時,數據肯定就會發生錯誤。這時我們可以利用 Last-Modified 來標識最后的修改時間,這樣就可以判斷服務器上的文件是否發生改變。和 Last-Modified 具有同樣功能的還有 if-Modified-Since,它倆的不同點是 Last-Modified 由服務器發送給客戶端,而 if-Modified-Since 是由客戶端發出, if-Modified-Since 將先前服務器發送給客戶端的 Last-Modified 發送給服務器,服務器進行最后修改時間驗證后,來告知客戶端是否需要重新從服務器端獲取新內容。客戶端判斷是否需要更新,只需要判斷服務器返回的狀態碼即可,206 代表不需要重新獲取接著下載就行,200代表需要重新獲取。但是 Last-Modified 和 if-Modified-Since 存在一些問題:
某些文件只是修改了修改時間而內容卻沒變,這時我們并不希望客戶端重新緩存這些文件;
某些文件修改頻繁,有時一秒要修改十幾次,但是 if-Modified-Since 是秒級的,無法判斷比秒更小的級別;部分服務器無法獲得精確的修改時間。要解決上述問題我們就需要用到 Etag ,只需將相關標記(例如文件版本號等)放在引號內即可。
當使用校驗的時候我們不需要手動實現驗證,只需要利用 if-Range 結合 Last-Modified 或者 Etage 來判斷是否發生改變,如果沒有發生改變服務器將向客戶端發送剩余的部分,否則發送全部。
注意:If-Range 必須與 Range 配套使用。缺少其中任意一個另一個都會被忽略。
秒傳
原理
秒傳利文件的MD5,首先將文件的MD5發送個服務器,服務器傳輸過來的MD5判斷服務器上是否存在相同類型的文件,如果存在就將文件復制一份,而不是本地上傳。這樣就是先的秒傳功能。
MD5
秒傳涉及到了MD5,那么什么MD5呢?MD5的英文全稱是 Message-Digest Algorith 5 ,是計算機廣泛使用的算法之一。MD5 會為文件產生唯一的“指紋”,任何改動都會改變文件指紋。它以 512位分組來處理信息,每個分組又被分為16個32位分組,經過處理后輸出4個32位分組,最后將輸出的4個32位分組進行級聯生成128位散列值。
MD5的具有壓縮性、易計算、抗修改、弱抗碰撞和強抗碰撞。下面我們一一來講解:
- 壓縮性:任意長度數據,生成的MD5值長度是固定的;
- 易計算:可以很方便的從原始數據計算出MD5;
- 抗修改:對原始數據的任何修改,都會改變MD5;
- 弱抗碰撞和強抗碰撞:很難找到具有相同MD5的數據。
破解謠言:有人說網盤能秒傳證明數據在網盤服務器是不加密的,有數據庫查看權限的人都可以看,所以私密文件最好在本地磁盤加密后再上傳到網盤中。這句話是錯誤的,正規的網盤服務器只是驗證了文件的MD5碼,文件還是加密存放的。
總結
這篇文章講解了斷點續傳和秒傳的知識,也講解了它們所使用技術的相關知識點。這些知識可以用在任何編程語言的斷點續傳和秒傳的開發中,因此這篇文章我并沒有根據具體的語言講解。
作者簡介:朱鋼,筆名喵叔,CSDN博客專家,.NET高級開發工程師,7年一線開發經驗,參與過電子政務系統和AI客服系統的開發,以及互聯網招聘網站的架構設計,目前就職于北京恒創融慧科技發展有限公司,從事企業級安全監控系統的開發。
【END】