Square的OkHttp。下载进度

26

在使用Square的OkHttp时,是否有任何方法可以获取下载文件的进度?

我在Recipes中没有找到任何解决方案。

虽然他们有Call类可以异步获取内容,但没有方法可以获取当前进度。

3个回答

31

抱歉,答案很明显,问题有点愚蠢。只需要像往常一样读取InputStream即可。

private class AsyncDownloader extends AsyncTask<Void, Long, Boolean> {
    private final String URL = "file_url";

    @Override
    protected Boolean doInBackground(Void... params) {
        OkHttpClient httpClient = new OkHttpClient();
        Call call = httpClient.newCall(new Request.Builder().url(URL).get().build());
        try {
            Response response = call.execute();
            if (response.code() == 200) {
                InputStream inputStream = null;
                try {
                    inputStream = response.body().byteStream();
                    byte[] buff = new byte[1024 * 4];
                    long downloaded = 0;
                    long target = response.body().contentLength();

                    publishProgress(0L, target);
                    while (true) {
                        int readed = inputStream.read(buff);
                        if(readed == -1){
                            break;
                        }
                        //write buff
                        downloaded += readed;
                        publishProgress(downloaded, target);
                        if (isCancelled()) {
                            return false;
                        }
                    }
                    return downloaded == target;
                } catch (IOException ignore) {
                    return false;
                } finally {
                    if (inputStream != null) {
                        inputStream.close();
                    }
                }
            } else {
                return false;
            }
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    protected void onProgressUpdate(Long... values) {
        progressBar.setMax(values[1].intValue());
        progressBar.setProgress(values[0].intValue());

        textViewProgress.setText(String.format("%d / %d", values[0], values[1]));
    }

    @Override
    protected void onPostExecute(Boolean result) {
        textViewStatus.setText(result ? "Downloaded" : "Failed");
    }
}

7
有没有更优雅的方法来完成这件事?比如说okHttpClient.newCall(request).notifyProgress(callback)...或者类似这样的东西... - josketres
很好的回答,但还有一个问题...我看到我们有一个输入流...要将其传递到文件中,我们是否必须再次遍历整个流并将其转换为文件?您能展示一下如何获取已下载的文件对象吗? - Marcus Gabilheri
@MarcusGabilheri,你是在说这个吗?https://dev59.com/-Wgv5IYBdhLWcg3wF85P#10857407 - Kalyaganov Alexey
@FrancisShi 是的,但您可以扩展此解决方案并添加字节阈值以进行发布。 - Kalyaganov Alexey
20
通常情况下,这个答案是错误的,因为它展示了从响应输入流中复制字节的进度,而该流仅当文件完全下载时才可用。因此,如果您有一个大小为10兆字节的文件和1MB/s的网络速度,您将在10秒钟内看到0%,然后非常快地从0%进展到100%。 - Semyon Danilov
显示剩余5条评论

9

-1
在 while 循环中,每次发布进度时都会被阻塞。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接