okhttp-OkGo icon indicating copy to clipboard operation
okhttp-OkGo copied to clipboard

关于支持不可断点下载的资源的几条建议

Open blueskky opened this issue 4 years ago • 2 comments

1.本库对于不可断点下载的资源支持很差,如果常规的下载会报异常 breakpoint file has expired 。 2.通过手动设置 task.progress.totalSize 后可以下载不可断点下载资源,但是强杀进程再次下载时文件全量下载,追加到上次下载了部分的文件后。导致下载的文件比实际文件要大,进度也会超过100%。假如手动设置的长度和文件实际长度不一致,还是会下载失败 3.对于不可断点下载的资源,而又不知道他的长度时,那就下载不了了。产品这时候跳出去说,你看浏览器都可以下载啊,你无言以对

我下载本库后做了一些 修改,在DownloadTask 的run方法中增加了资源是否支持断点下载的判断,再分情况处理下,基本解决了上述问题。但是本人很菜,修改的感觉不是健壮,希望作者大牛可以把这个优化下。

blueskky avatar Jul 10 '20 14:07 blueskky

怎么修改的?分享一下呗

gh4work avatar Jan 11 '21 09:01 gh4work

怎么修改的?分享一下呗

以下是DownloadTask 中run 方法的修改

@Override public void run() { //check breakpoint long startPosition = progress.currentSize; if (startPosition < 0) { startPosition = 0; } if (startPosition > 0) { if (!TextUtils.isEmpty(progress.filePath)) { File file = new File(progress.filePath); if (!file.exists()) { startPosition = 0; } } }

    //request network from startPosition
    Response response;
    try {
        Request<?, ? extends Request> request = progress.request;
        request.headers(HttpHeaders.HEAD_KEY_RANGE, "bytes=" + startPosition + "-");
        response = request.execute();
    } catch (IOException e) {
        postOnError(progress, e);
        return;
    }

    //check network data
    int code = response.code();
    if (code == 404 || code >= 500) {
        postOnError(progress, HttpException.NET_ERROR());
        return;
    }

    ResponseBody body = response.body();
    if (body == null) {
        postOnError(progress, new HttpException("response body is null"));
        return;
    }

    Headers headers = response.headers();
    if (headers != null) {
        String length = headers.get("Content-Length");
        String acceptRange = headers.get("Accept-Ranges");

        if (!TextUtils.isEmpty(length) && Long.parseLong(length) > 0 && "bytes".equals(acceptRange)) {
            supportBP = true;
        }
    }

    //不支持断点的 会全量下载,所以先删除以前下载的部分
    if (!supportBP) {
        if (!TextUtils.isEmpty(progress.filePath)) {
            File file = new File(progress.filePath);
            if (file.exists()) {
                IOUtils.delFileOrFolder(file);
                startPosition = 0;
            }
        }
    }

    if (progress.totalSize == -1) {
        if (supportBP) {
            progress.totalSize = body.contentLength();
        } else {
            progress.totalSize = totalLength;
        }
    }
    //模糊进度
    if (progress.totalSize == 0) {
        progress.indeterminate = true;
    }

    //create filename
    String fileName = progress.fileName;
    if (TextUtils.isEmpty(fileName)) {
        fileName = HttpUtils.getNetFileName(response, progress.url);
        progress.fileName = fileName;
    }
    if (!IOUtils.createFolder(progress.folder)) {
        postOnError(progress, StorageException.NOT_AVAILABLE());
        return;
    }

    //create  file
    File file;
    if (TextUtils.isEmpty(progress.filePath)) {
        file = new File(progress.folder, fileName);
        progress.filePath = file.getAbsolutePath();
    } else {
        file = new File(progress.filePath);
    }
    if (startPosition > 0 && !file.exists()) {

// postOnError(progress, OkGoException.BREAKPOINT_EXPIRED()); restart(); return; }

// if (startPosition > progress.totalSize) { // postOnError(progress, OkGoException.BREAKPOINT_EXPIRED()); // return; // } if (startPosition == 0 && file.exists()) { IOUtils.delFileOrFolder(file); } if (startPosition == progress.totalSize && startPosition > 0) { if (file.exists() && startPosition == file.length()) { postOnFinish(progress, file); return; } else { postOnError(progress, OkGoException.BREAKPOINT_EXPIRED()); return; } }

    //start downloading
    RandomAccessFile randomAccessFile;
    try {
        randomAccessFile = new RandomAccessFile(file, "rw");
        randomAccessFile.seek(startPosition);
        progress.currentSize = startPosition;
    } catch (Exception e) {
        postOnError(progress, e);
        return;
    }
    try {
        DownloadManager.getInstance().replace(progress);
        download(body.byteStream(), randomAccessFile, progress);
    } catch (IOException e) {
        postOnError(progress, e);
        return;
    }

    //check finish status
    if (progress.status == Progress.PAUSE) {
        postPause(progress);
    } else if (progress.status == Progress.LOADING) {
        if (supportBP) {
            if (file.length() == progress.totalSize) {
                postOnFinish(progress, file);
            } else {
                postOnError(progress, OkGoException.BREAKPOINT_EXPIRED());
            }
        } else {
            postOnFinish(progress, file);
        }
    } else {
        postOnError(progress, OkGoException.UNKNOWN());
    }
}

blueskky avatar Jan 14 '21 09:01 blueskky