1. 程式人生 > >擼了個多執行緒斷點續傳下載器,我從中學習到了這些知識

擼了個多執行緒斷點續傳下載器,我從中學習到了這些知識

> 文章已經收錄在 [Github.com/niumoo/JavaNotes](https://github.com/niumoo/JavaNotes) ,更有 Java 程式設計師所需要掌握的核心知識,歡迎Star和指教。 > 歡迎關注我的[公眾號](https://github.com/niumoo/JavaNotes#%E5%85%AC%E4%BC%97%E5%8F%B7),文章每週更新。 感謝看客老爺點進來了,週末閒來無事,想起**同事強哥**的那句話:“你有沒有玩過**斷點續傳**?” 當時轉念一想,**斷點續傳**下載用的確實不少,具體細節嘛,真的沒有去思考過啊。這不,思考過後有了這篇文章。感謝強哥,讓我有了一篇可以水的文章,下面會用純 Java 無依賴實現一個簡單的**多執行緒斷點續傳下載器**。 這篇水文章到底有什麼內容呢?先簡單列舉一下,順便思考幾個問題。 1. 斷點續傳的原理。 2. 重啟續傳檔案時,怎麼保證檔案的一致性? 3. 同一個檔案多執行緒下載如何實現? 4. **網速頻寬固定,為什麼多執行緒下載可以提速?** 多執行緒斷點續傳會用到哪些知識呢?上面已經丟擲了幾個問題,不放思考一下。下面會針對上面的四個問題一一進行解釋,現在大多數的服務都可以線上提供,下載使用的場景越來越少,不過這不妨礙我們對原理的探求。 ## 斷點續傳的原理 想要了解斷點續傳是如何實現的,那麼肯定是要了解一下 HTTP 協議了。HTTP 協議是網際網路上應用最廣泛網路傳輸協議之一,它基於 **TCP/IP** 通訊協議來傳遞資料。所以斷點續傳的奧祕也就隱藏在這 HTTP 協議中了。 我們都知道 HTTP 請求會有一個 **Request header** 和 **Response header** ,就在這請求頭和響應頭裡,有一個和 Range 相關的引數。下面通過百度網盤的 pc 客戶端下載連結進行測試。 使用 cURL 檢視 response header. 如果你想知道更多關於 cURL 的用法,可以看我之前的一篇文章 :[進來領略下cURL的獨門絕技](https://mp.weixin.qq.com/s/jK4ctq5VQjw4oPSO0gEp6Q)。 ```shell $ curl -I http://wppkg.baidupcs.com/issue/netdisk/yunguanjia/BaiduYunGuanjia_7.0.1.1.exe HTTP/1.1 200 OK Server: JSP3/2.0.14 Date: Sat, 25 Jul 2020 13:41:55 GMT Content-Type: application/x-msdownload Content-Length: 65804256 Connection: keep-alive ETag: dcd0bfef7d90dbb3de50a26b875143fc Last-Modified: Tue, 07 Jul 2020 13:19:46 GMT Expires: Sat, 25 Jul 2020 14:05:19 GMT Age: 257796 Accept-Ranges: bytes Cache-Control: max-age=259200 Content-Disposition: attachment;filename="BaiduYunGuanjia_7.0.1.1.exe" x-bs-client-ip: MTgwLjc2LjIyLjU0 x-bs-file-size: 65804256 x-bs-request-id: MTAuMTM0LjM0LjU2Ojg2NDM6NDM4MTUzMTE4NTU3ODc5MTIxNzoyMDIwLTA3LTA3IDIyOjAxOjE1 x-bs-meta-crc32: 3545941535 Content-MD5: dcd0bfef7d90dbb3de50a26b875143fc superfile: 2 Ohc-Response-Time: 1 0 0 0 0 0 Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS, HEAD Ohc-Cache-HIT: bj2pbs54 [2], bjbgpcache54 [4] ``` 可以看到百度 pc 客戶端的 response header 資訊有很多,我們只需要重點關注幾個。 ```shell Content-Length: 65804256 // 請求的檔案的大小,單位 byte Accept-Ranges: bytes // 是否允許指定傳輸範圍,bytes:範圍請求的單位是 bytes (位元組),none:不支援任何範圍請求單位, Last-Modified: Tue, 07 Jul 2020 13:19:46 GMT // 服務端檔案最後修改時間,可以用於校驗檔案是否更改過 x-bs-meta-crc32: 3545941535 // crc32,可以用於校驗檔案是否更改過 ETag: dcd0bfef7d90dbb3de50a26b875143fc //Etag 標籤,可以用於校驗檔案是否更改過 ``` 可見並不見得所有下載都支援斷點續傳,只有在 response header 中有 `Accept-Ranges: bytes ` 欄位時才可以斷點續傳。如果有這個資訊,該怎麼斷點續傳呢?其實只需要在 response header 中指定 **Content-Range** 值就可以了。 **Content-Range** 使用格式有下面幾種。 ```shell Content