不知道为什么至少我找到的文章里面都没说过这个问题。记录一下。有些http的服务器在相应Range请求时的处理会有问题,比如请求为Range: bytes=0-1023,但是有可能会在0-1000时就认为已经传完被断开连接,原因不明,在我的使用中都是以一定的概率出现这种情况。

解决方案,不指定 Range 的结束字节,完全由客户端自行控制读多少后主动停止

private void doDownloadChunk(String url, Path tempFile, long startByte, long endByte,
                                 int threadId, AtomicLong downloadedBytes, long totalSize,
                                 DownloadTask task, AtomicLong readNubmer) throws IOException {

        Request request = new Request.Builder()
                .url(url)
                .addHeader("Range", "bytes=" + startByte + "-")//只写请求的起始,不写结束
                .build();

        long totalRead = 0;
        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("请求失败: " + response.code());
            }

            ResponseBody body = response.body();
            if (body == null) {
                throw new IOException("响应体为空");
            }
            long l = (endByte - startByte) + 1;

            // 使用FileChannel进行随机写入
            try (RandomAccessFile raf = new RandomAccessFile(tempFile.toFile(), "rw");
                 BufferedInputStream inputStream = new BufferedInputStream(body.byteStream())) {

                raf.seek(startByte);
                int cache = 8192;
                byte[] buffer = new byte[cache];
                int bytesRead = 0;


                while (true) {
                    //主要是这里需要计算还需要接收多少数据才能结束
                    if(l - totalRead < cache){
                        cache = (int) (l - totalRead);
                        if (cache == 0){
                            break;
                        }
                        buffer = new byte[cache];//这里我偷懒就直接创建新的对象了
                    }
                    bytesRead = inputStream.read(buffer);
                    if (bytesRead == -1) {
                        break; // 流结束
                    }

                    // 检查任务是否被取消
                    if (task.getStatus() == DownloadStatus.CANCELLED) {
                        break;
                    }

                    raf.write(buffer, 0, bytesRead);
                    totalRead += bytesRead;

                    // 更新总下载进度
                    downloadedBytes.addAndGet(bytesRead);
                    task.setDownloaded(downloadedBytes.get());
                }
            }
        }catch (Exception e){
            readNubmer.set(startByte + totalRead);
            throw e;
        }
    }