设计
- 把一个文件下载流分成 n 份,即 n 个线程各下载一份
- 等待所有线程搞定,之后将 n 个文件合并为一个
实例
以下载 QQ2020 PC为例,大小82MB
- 留意HTTP协议,先查看下它的HTTP response
文件类型是octet-stream ,支持范围请求 Accept-Ranges,大小 86025424 字节。 - HTTP request 构建,关键在于 headers 的 Range 参数,比如 Range: bytes=0-1023 表示只获取文件从 0 到 1023(包括)共1024字节的部分文件
- 实现 1 ,先发送一个 head 请求,获取文件的长度 contentLength
HttpRequest headReq = HttpRequest
.newBuilder(qqUri)
.method("HEAD", BodyPublishers.noBody() )
.build();
HttpResponse<Void> res = client.send(headReq, BodyHandlers.discarding());
long contentLength = res.headers().firstValueAsLong("content-length").orElseThrow();
- 实现 2,构建多个请求,这里是 5 个
long partLength = contentLength / 5 + 1;
HttpRequest.Builder baseRequest = HttpRequest.newBuilder(qqUri).GET();
CountDownLatch latch = new CountDownLatch(5);
List<Callable<HttpResponse<Path>>> tasks = new ArrayList<>();
int start = 0;
for (int i = 0; i < 5; i++) {
String range = "bytes=" + start + "-" + (start += partLength);
var req = baseRequest.copy().header("Range", range).build