断点续传

Posted by OOFTF Blog on May 15, 2021

断点续传

理论基础

  • http协议从1.1开始支持获取文件的部分内容,这为并行下载以及断点续传提供了技术支持。它通过在Header里两个参数实现的,客户端发请求时对应的是Range,服务器端响应时对应的是Content-Range;
  • RandomAccessFile.seek() 可以设置文件指针偏移量

OkHttp 断点续传实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**
 * 使用OkHttp下载文件,支持断点续传
 */
public void downloadByOkHttp() throws IOException {
    // 文件下载地址
    String url = "https://alissl.ucdl.pp.uc.cn/fs08/2019/07/05/1/110_17e4089aa3a4b819b08069681a9de74b.apk";
    // 创建下载文件对象
    File directory = Environment.getExternalStorageDirectory();
    File file = new File(directory, "20190715.apk");
    RandomAccessFile accessFile = new RandomAccessFile(file, "rw");
    // 断点续传:重新开始下载的位置:file.length()
    String range = String.format(Locale.CHINESE, "bytes=%d-", file.length());
    OkHttpClient client = new OkHttpClient();
    Request request = new Request.Builder()
            .url(url)
            .header("range", range)
            .build();
    // 使用OkHttp请求服务器
    Call call = client.newCall(request);
    Response response = call.execute();
    // 连接服务器成功
    ResponseBody body = response.body();
    System.out.println("文件大小:" + body.contentLength());
    // 移动文件指针到断点续传的位置
    accessFile.seek(file.length());
    // 开始断点续传
    InputStream inputStream = body.byteStream();
    byte[] bytes = new byte[1024];
    int len = inputStream.read(bytes);
    while (len != -1) {
        accessFile.write(bytes, 0, len);
        System.out.println("已下载字节:" + file.length());
        len = inputStream.read(bytes);
    }
    System.out.println("文件下载完毕:" + accessFile.getFilePointer());
}