嚴格意義上來說,斷點續傳功能需要服務端和客戶端同時支持,但是現在大多主流服務器或者框架已經默認支持,所以本文只討論客戶端實現。
這裏以okhttp下載爲例子說明,關鍵點是在訪問的頭裏面添加“RANGE”參數,這個參數告訴服務端你要從一個文件的某個位置開始下載。比如你傳如的“RNAGE”參數是100,要下載的服務端的文件大小爲200,然後就會從文件100的地方開始給你。代碼實現如下:
addHeader("RANGE", "bytes=" + startPoint + "-")
在httpclient header中添加一個“RANGE”參數。
獲取到服務端的io流之後,通過RandomAccessFile這個api的seek(long position) api來實現文件的追加,最終實現文件的斷點續傳下載功能。
接受服務端返回io流追加寫入文件代碼如下:
ResponseBody body = response.body(); InputStream in = body.byteStream(); FileChannel channelOut = null; // 隨機訪問文件,可以指定斷點續傳的起始位置 RandomAccessFile randomAccessFile = null; long sum = 0; File file = null; try { final long total = body.contentLength(); DLogUtils.e("ResumeFileCallBack","file total : "+total); File dir = new File(destFileDir); if (!dir.exists()) { dir.mkdirs(); } file = new File(dir, destFileName); downloadFileSize = file.length(); DLogUtils.e("ResumeFileCallBack","already load file size : "+downloadFileSize); sum += startsPoint;//累加已經下載的大小,方便統計進度,startsPoint這個參數可以傳入 randomAccessFile = new RandomAccessFile(file, "rwd"); randomAccessFile.seek(startsPoint); byte[] buffer = new byte[1024]; int len; while ((len = in.read(buffer)) != -1) { sum += len; randomAccessFile.write(buffer,0,len); final long finalSum = sum; OkHttpUtils.getInstance().getDelivery().execute(new Runnable() { @Override public void run() { //更新進度 inProgress(finalSum * 1.0f / (total+downloadFileSize),total,id); } }); } } catch (IOException e) { e.printStackTrace(); }finally { try { in.close(); if (channelOut != null) { channelOut.close(); } if (randomAccessFile != null) { randomAccessFile.close(); } } catch (IOException e) { e.printStackTrace(); } }