java 断点续传 开源_java断点续传原理
先說說斷點續傳的原理:這是HTTP 1.1協議的一部分,并不需要客戶端特意去做多么復雜的事情。以前我曾經看過一個單位的技術標書,其中有下載的斷點續傳這一要求,給出的offer居然還挺高的...
簡單的說,只要利用了HTTP協議(http://www.ietf.org/rfc/rfc2616.txt)中的如下字段來和服務器端交互,就可以實現文件下載的斷點續傳:
Range : 用于客戶端到服務器端的請求,可通過該字段指定下載文件的某一段大小,及其單位。典型的格式如:
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? 下載第一以及最后一個字節的內容(這個看上去有點變態...)
Accept-Ranges : 用于服務器端到客戶端的應答,客戶端通過該字段可以判斷服務器是否支持斷點續傳(注意RFC中注明了這一部分并不是必須的)。格式如下:
Accept-Ranges: bytes? 表示支持以bytes為單位進行傳輸。
Accept-Ranges: none? 表示不支持
Content-Ranges : 用于服務器端到客戶端的應答,與Accept-Ranges在同一個報文內,通過該字段指定了返回的文件資源的字節范圍。格式如下:
Content-Ranges: bytes 0-499/1234? 大小為1234的文件的第0-499字節范圍的內容
Content-Ranges: bytes 734-1233/1234? 大小為1234字節的文件的第734-結尾范圍的內容
據此我們可以知道,斷點續傳這個功能是需要客戶端和服務器端同時支持才能完成。
Android平臺面向開發者提供了DownloadManager這個服務(service),可以用來完成下載,同時異步地得到下載進度的實時更新提示。原生的瀏覽器,Android Market以及GMail等客戶端都使用了該接口。該接口也部分的提供了斷點續傳功能:如果在下載過程中遇到網絡錯誤,如信號中斷等,DownloadManager會在網絡恢復時嘗試斷點續傳繼續下載該文件。但不支持由用戶發起的暫停然后斷點續傳。
要擴展該功能也不難,只要為下載任務新增一種狀態(類似paused_by_user),以及相關邏輯即可,這里暫不贅述,把話題引到一些常見問題上。
1. 關于ETag
RFC中的定義有些抽象,簡單的說,ETag可以用來標識/保證文件的唯一性或完整性,你可以把它看作是服務器為某個文件生產的唯一標識值,每次文件有更新該值就會變化。通過這種機制客戶端可以檢查某個文件在斷點續傳(當然它不僅僅用于斷點續傳)的前后是否有所改動:如果ETag改變了就應該重新下載整個文件以保證它的完整性。
但是在現實環境中,有一些服務器并不返回ETag字段,同時它又是支持斷點續傳的,這種情況下原生的Android就會認為服務器端不支持斷點續傳。這應該不是什么bug,僅僅是這么實現而已。還有更麻煩的情況是,有些服務器給了錯誤的ETag,但文件是從未更改的,這時候要想從客戶端修改這個“bug”,估計只能忽略ETag值了。
2. 關于HTTP 206
RFC中定義了斷點續傳時服務器端的應答情況:如果支持且返回的內容如請求所要求的那樣,是該文件的一部分,則使用HTTP 206狀態碼;如果不支持,或需要返回整個文件,則使用HTTP 200狀態碼。但是現實網絡中有些服務器不管三七二十一,都返回200。沒辦法,如果還是想從客戶端來修改這個“bug”,那就多做一些判斷處理吧:如果服務器指定了“Content-Ranges”,就忽略HTTP 200的狀態碼。
附圖一張,簡述流程。見附件
補記:有一次被問起如何在原生的Android手機上暫停一個下載任務,回頭再斷點續傳。我想是不是可以在下載過程中將手機信號關閉,下次再打開手機信號時,那個下載任務就可以自動接著續傳了(當然前提是服務器支持)...這個用例沒多大實用價值,懶得實測了
總結
以上是生活随笔為你收集整理的java 断点续传 开源_java断点续传原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: laravel项目中css样式表的背景图
- 下一篇: POJ2190 HDU2714 ISBN