严格意义上来说,断点续传功能需要服务端和客户端同时支持,但是现在大多主流服务器或者框架已经默认支持,所以本文只讨论客户端实现。
这里以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(); } }