[TOC]
## 什么是斷點續傳
指的是在上傳/下載時,將任務(一個文件或壓縮包)人為的劃分為幾個部分,每一個部分采用一個線程進行上傳/下載,如果碰到網絡故障,可以從已經上傳/下載的部分開始繼續上傳/下載未完成的部分,而沒有必要從頭開始上傳/下載。可以節省時間,提高速度。
## Http 怎么支持斷點續傳的?
Http 1.1 協議中默認支持獲取文件的部分內容,這其中主要是通過頭部的兩個參數:Range 和 Content Range 來實現的。客戶端發請求時對應的是 Range ,服務器端響應時對應的是 Content-Range。
### Range
客戶端想要獲取文件的部分內容,那么它就需要請求頭部中的 Range 參數中指定獲取內容的起始字節的位置和終止字節的位置,它的格式一般為:
~~~
Range:(unit=first byte pos)-[last byte pos]
~~~
例如:
~~~
Range: bytes=0-499 表示第 0-499 字節范圍的內容
Range: bytes=500-999 表示第 500-999 字節范圍的內容
Range: bytes=-500 表示最后 500 字節的內容
Range: bytes=500- 表示從第 500 字節開始到文件結束部分的內容
Range: bytes=0-0,-1 表示第一個和最后一個字節
Range: bytes=500-600,601-999 同時指定幾個范圍
~~~
### Content Range
在收到客戶端中攜帶 Range 的請求后,服務器會在響應的頭部中添加 Content Range 參數,返回可接受的文件字節范圍及其文件的總大小。它的格式如下:
~~~
Content-Range: bytes (unit first byte pos) - [last byte pos]/[entity legth]
~~~
例如:
~~~
Content-Range: bytes 0-499/22400 // 0-499 是指當前發送的數據的范圍,而 22400 則是文件的總大小。
~~~
### 使用斷點續傳和不使用斷點續傳的響應內容區別
* 不使用斷點續傳
~~~
HTTP/1.1 200 Ok
~~~
* 使用斷點續傳
~~~
HTTP/1.1 206 Partial Content
~~~
## 處理請求資源發生改變的問題
在現實的場景中,服務器中的文件是會有發生變化的情況的,那么我們發起續傳的請求肯定是失敗的,那么為了處理這種服務器文件資源發生改變的問題,在 RFC2616 中定義了 **Last-Modified** 和 **Etag** 來判斷續傳文件資源是否發生改變。
### Last-Modified & If-Modified-Since(文件最后修改時間)
* **Last-Modified**:記錄 Http 頁面最后修改時間的 Http 頭部參數,Last-Modified 是由服務端發送給客戶端的
* **If-Modified-Since**:記錄 Http 頁面最后修改時間的 Http 頭部參數,If-Modified-Since 是有客戶端發送給服務端的
* 驗證過程
* step 1:客戶端緩存從服務端獲取的頁面
* step 1:客戶端訪問相同頁面時,客戶端將服務器發送過來的 Last-Modified 通過 If-Modified-Since 發送給服務器
* step 2:服務器通過客戶端發送過來的 If-Modified-Since 進行判斷客戶端當前的緩存的頁面是否為最新的
* 如果不是最新的,那么就發送最新的頁面給客戶端
* 如果是最新的,那么就發送 304 告訴客戶端它本地緩存的頁面是最新的
### Etag & if-Range(文件唯一標志)
* Etag:作為文件的唯一標志,這個標志可以是文件的 hash 值或者是一個版本
* if-Range:用于判斷實體是否發生改變,如果實體未改變,服務器發送客戶端丟失的部分,否則發送整個實體。一般格式:
~~~
If-Range: Etag | HTTP-Date
復制代碼
~~~
If-Range 可以使用 Etag 或者 Last-Modified 返回的值。當沒有 ETage 卻有 Last-modified 時,可以把 Last-modified 作為 If-Range 字段的值
* 驗證過程
* step 1:客戶端發起續傳請求,頭部包含 Range 和 if-Range 參數
* step 2:服務器中收到客戶端的請求之后,將客戶端和服務器的 Etag 進行比對
* 相等:請求文件資源沒有發生變化,應答報文為 206
* 不相等:請求文件資源發生變化,應答報文為 200
## 檢查服務器是否支持斷點續傳

我們使用 curl 進行檢測,可以看出以下的幾個關鍵信息
* HTTP/1.1 206 Partial Content
* Content-Range: bytes 10-222/7877
* Etag: "1ec5-502264e2ae4c0"
* Last-Modified: Wed, 03 Sep 2014 10:00:27 GMT
## OkHttp 斷點下載
### 斷點下載思路
* step 1:判斷檢查本地是否有下載文件,若存在,則獲取已下載的文件大小 downloadLength,若不存在,那么本地已下載文件的長度為 0
* step 2:獲取將要下載的文件總大小(HTTP 響應頭部的 content-Length)
* step 3:比對已下載文件大小和將要下載的文件總大小(contentLength),判斷要下載的長度
* step 4:再即將發起下載請求的 HTTP 頭部中添加即將下載的文件大小范圍(Range: bytes = downloadLength - contentLength)
## 參考資料
[Android Okhttp 斷點續傳面試解析](https://juejin.cn/post/6844903854115389447)
- Android
- 四大組件
- Activity
- Fragment
- Service
- 序列化
- Handler
- Hander介紹
- MessageQueue詳細
- 啟動流程
- 系統啟動流程
- 應用啟動流程
- Activity啟動流程
- View
- view繪制
- view事件傳遞
- choreographer
- LayoutInflater
- UI渲染概念
- Binder
- Binder原理
- Binder最大數據
- Binder小結
- Android組件
- ListView原理
- RecyclerView原理
- SharePreferences
- AsyncTask
- Sqlite
- SQLCipher加密
- 遷移與修復
- Sqlite內核
- Sqlite優化v2
- sqlite索引
- sqlite之wal
- sqlite之鎖機制
- 網絡
- 基礎
- TCP
- HTTP
- HTTP1.1
- HTTP2.0
- HTTPS
- HTTP3.0
- HTTP進化圖
- HTTP小結
- 實踐
- 網絡優化
- Json
- ProtoBuffer
- 斷點續傳
- 性能
- 卡頓
- 卡頓監控
- ANR
- ANR監控
- 內存
- 內存問題與優化
- 圖片內存優化
- 線下內存監控
- 線上內存監控
- 啟動優化
- 死鎖監控
- 崩潰監控
- 包體積優化
- UI渲染優化
- UI常規優化
- I/O監控
- 電量監控
- 第三方框架
- 網絡框架
- Volley
- Okhttp
- 網絡框架n問
- OkHttp原理N問
- 設計模式
- EventBus
- Rxjava
- 圖片
- ImageWoker
- Gilde的優化
- APT
- 依賴注入
- APT
- ARouter
- ButterKnife
- MMKV
- Jetpack
- 協程
- MVI
- Startup
- DataBinder
- 黑科技
- hook
- 運行期Java-hook技術
- 編譯期hook
- ASM
- Transform增量編譯
- 運行期Native-hook技術
- 熱修復
- 插件化
- AAB
- Shadow
- 虛擬機
- 其他
- UI自動化
- JavaParser
- Android Line
- 編譯
- 疑難雜癥
- Android11滑動異常
- 方案
- 工業化
- 模塊化
- 隱私合規
- 動態化
- 項目管理
- 業務啟動優化
- 業務架構設計
- 性能優化case
- 性能優化-排查思路
- 性能優化-現有方案
- 登錄
- 搜索
- C++
- NDK入門
- 跨平臺
- H5
- Flutter
- Flutter 性能優化
- 數據跨平臺