日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

Android 断点续传实现原理

發(fā)布時(shí)間:2024/9/30 Android 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android 断点续传实现原理 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/zhaoyanjun6/article/details/120956134
本文出自【趙彥軍的博客】

文章目錄

  • 下載原理
  • 斷點(diǎn)續(xù)傳原理
    • 1、java.io.RandomAccessFile
    • 2、請(qǐng)求響應(yīng)碼及Header
    • 3、處理請(qǐng)求資源發(fā)生改變的問(wèn)題
    • 4、文件可復(fù)用判斷

下載原理

在介紹斷點(diǎn)續(xù)傳之前,我們先說(shuō)說(shuō)下載的原理。代碼示例用 OkHttp 作為示例。

下載核心思路是把 responseBody 寫(xiě)入文件,核心代碼如下:

但是這種做法有個(gè)明顯的問(wèn)題,假如手機(jī)在下載文件的時(shí)候下載了80%,某些原因斷網(wǎng)了,如果不支持?jǐn)帱c(diǎn)續(xù)傳,那就只有被迫重頭開(kāi)始下載。但是如果有斷點(diǎn)續(xù)傳的加持,就只需要下載最后 20% 的資源,避免重新下載。

斷點(diǎn)續(xù)傳原理

1、java.io.RandomAccessFile

斷點(diǎn)續(xù)傳/下載需要使用到 java.io.RandomAccessFile 類(lèi),RandomAccessFile 的實(shí)例支持讀取和寫(xiě)入隨機(jī)訪問(wèn)文件,它也可以 seek(long pos) 設(shè)置從此文件的開(kāi)頭開(kāi)始測(cè)量的文件指針偏移量,在該位置進(jìn)行下一次讀取或?qū)懭氩僮鳌:?jiǎn)單點(diǎn)說(shuō)就是可以通過(guò) seek(long pos)方法跳過(guò)pos字節(jié)開(kāi)始寫(xiě)入字節(jié)。

如何創(chuàng)建一個(gè) RandomAccessFile ?

//rw:支持可讀可寫(xiě) val file = RandomAccessFile(file, "rw")

假如我有一段文本要寫(xiě)入文件,但是需要從文件的第100個(gè)字節(jié)開(kāi)始寫(xiě),那么需要調(diào)用 seek(long pos ) 方法跳過(guò)前 100 個(gè)字節(jié), 具體實(shí)現(xiàn)如下:

val file = RandomAccessFile(file, "rw") file.seek(100) file.writeBytes(.....)

所以,我們可以把 responseBody 寫(xiě)入文件的實(shí)現(xiàn)改成如下實(shí)現(xiàn):

2、請(qǐng)求響應(yīng)碼及Header

正常情況下,我們下載一個(gè)文件,響應(yīng)碼是 200

responseBody 返回的是整個(gè)文件的內(nèi)容。如何才能返回部分內(nèi)容?
在實(shí)現(xiàn)分塊請(qǐng)求之前,首先要判斷服務(wù)器是否支持分塊返回,標(biāo)志是 Access-Ranges ,值為 bytes 就代表服務(wù)器支持分塊返回,也就是支持?jǐn)帱c(diǎn)續(xù)傳。

所以,我們可以封裝一個(gè)方法,來(lái)判斷服務(wù)是否支持?jǐn)帱c(diǎn)續(xù)傳

在確定了服務(wù)器支持分塊傳輸后,我們就可以在請(qǐng)求資源的時(shí)候,添加 header 請(qǐng)求 Range 字段,來(lái)指定請(qǐng)求實(shí)體的范圍。它的范圍取值是在 0-Content-Length 之間,使用 - 分割。

例如已經(jīng)下載了 1000 bytes 的資源內(nèi)容,想接著繼續(xù)下載之后的資源內(nèi)容,只要在 HTTP 請(qǐng)求頭部,增加 Range:bytes=1000- 就可以了。

Range 還有幾種不同的方式來(lái)限定范圍,可以根據(jù)需要靈活定制:

  • 500-1000:指定開(kāi)始和結(jié)束的范圍。
  • 500- :指定開(kāi)始區(qū)間,一直傳遞到結(jié)束。這個(gè)就比較適用于斷點(diǎn)續(xù)傳、或者在線播放等等。
  • -500:無(wú)開(kāi)始區(qū)間,只意思是需要最后 500 bytes 的內(nèi)容實(shí)體。
  • 100-300,1000-3000:指定多個(gè)范圍,這種方式使用的場(chǎng)景很少,了解一下就好了。

具體舉例如下:

通過(guò)抓包我們發(fā)現(xiàn),添加了 Range 后,請(qǐng)求響應(yīng)碼變成了 206


并且添加 Range 后,響應(yīng)的 responseBody 就不再是整個(gè)文件的內(nèi)容了,而是一個(gè)片段,我們只需要把這個(gè)片段的數(shù)據(jù)直接寫(xiě)入文件就可以。

注意事項(xiàng),如何計(jì)算 Range 請(qǐng)求頭的開(kāi)始值,一般取用緩存文件的長(zhǎng)度值,如下

val start = targetFile.length()

3、處理請(qǐng)求資源發(fā)生改變的問(wèn)題

在現(xiàn)實(shí)的場(chǎng)景中,服務(wù)器中的文件是會(huì)有發(fā)生變化的情況的,那么我們發(fā)起續(xù)傳的請(qǐng)求肯定是失敗的

那么為了處理這種服務(wù)器文件資源發(fā)生改變的問(wèn)題,在 RFC2616 中定義了 Last-Modified和 Etag 來(lái)判斷續(xù)傳文件資源是否發(fā)生改變。

  • Last-Modified:記錄 Http 頁(yè)面最后修改時(shí)間的 Http 頭部參數(shù),Last-Modified 是由服務(wù)端發(fā)送給客戶(hù)端的
  • Etag:作為文件的唯一標(biāo)志,這個(gè)標(biāo)志可以是文件的 hash 值或者是一個(gè)版本

我們封裝一個(gè)方法用來(lái)獲取這兩個(gè)值

if-Range:用于判斷實(shí)體是否發(fā)生改變,如果實(shí)體未改變,服務(wù)器發(fā)送客戶(hù)端丟失的部分,否則發(fā)送整個(gè)實(shí)體。一般格式:

If-Range: Etag | HTTP-Date

If-Range 可以使用 Etag 或者 Last-Modified 返回的值。當(dāng)沒(méi)有 ETage 卻有 Last-modified 時(shí),可以把 Last-modified 作為 If-Range 字段的值。實(shí)現(xiàn)舉例如下:

關(guān)于 Etag 、Last-Modified 注意事項(xiàng):

  • 當(dāng)?shù)谝淮握?qǐng)求資源的時(shí)候,獲取 Etag/Last-Modified 值,并且保存到本地
  • 當(dāng)下一次需要斷點(diǎn)續(xù)傳的時(shí)候,把 Etag/Last-Modified 值取出,添加到請(qǐng)求頭 If-Range 字段

4、文件可復(fù)用判斷

在文件下載完成后,如果又發(fā)起了一次下載請(qǐng)求,那么此時(shí)不應(yīng)該重復(fù)下載的。需要做可復(fù)用判斷,思路如下

  • 1、獲取目前已下載文件的大小
  • 2、獲取文件url 獲取服務(wù)器文件大小
  • 3、如果已下載大小等于服務(wù)器文件大小,則復(fù)用已下載的文件

舉例如下:

//獲取已下載文件長(zhǎng)度 val downloadLength = targetFile.length() //獲取服務(wù)器文件長(zhǎng)度 val contentLength = responseBody.contentLength() //兩者長(zhǎng)度對(duì)比 if(downloadLength == contentLength){//復(fù)用已下載文件,不再重復(fù)下載 }

總結(jié)

以上是生活随笔為你收集整理的Android 断点续传实现原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。