为什么我只能每次从okhttp.Response InputStream读取2048个字节?

7

我正在使用OkHttp GET请求下载文件:

import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
...
OkHttpClient okClient = new OkHttpClient();
Request request = Request.Builder().url(url).get();
Response response = okClient.newCall(request).execute();

我从响应体中读取数据,并使用缓冲区大小为4096的BufferedInputStream进行装饰:

BufferedInputStream in = new BufferedInputStream(response.body().byteStream(), 4096);

然而,当我尝试从缓冲区读取时,第一次读取返回1179字节。之后,我只能每次读取2048字节:

byte[] buffer = new byte[4096];
while (true) {
    int bytesRead = in.read(buffer); //bytesRead is always 2048, except the first read
    if (bytesRead == -1) break;
}

以下是几个相关问题:

  1. 为什么第一次读取返回1179字节?是否是某种文件头导致的?
  2. InputStream中的读取为什么会被分页到2048字节大小,而不是BufferedInputStream包装器指定的值?
  3. 是否有一种方法可以配置OkHttpClient从缓冲区中读取超过2048字节的数据?
1个回答

5
第一次读取返回1179个字节可能是文件头导致的吗?
你正在读取的响应的HTTP标头为869个字节。
从InputStream读取为什么要分页到2048个字节的大小,而不是由BufferedInputStream包装器指定的值?
您需要深入研究BufferedInputStream才能找出为什么它没有将两个页面合并在一起。
OkHttp的InputStream使用其池来保存分配,因此它每次处理2048个字节的块。
是否有一种方法可以配置 OkHttpClient 以从缓冲区读取超过2048个字节?
不行。

根据您所做的工作,通常使用response.body().source()中的BufferedSource比使用BufferedInputStream更好。您可以在Okio repo上了解更多有关它们的信息。


谢谢解释,Jake。我不知道source()方法,我会去看看Okio。 - weefbellington
在这种情况下,我们该如何下载文件?从我的服务中下载10MB的文件需要很长时间。 - JustADev
没关系,我找到了解决速度问题的方法,可以参考这个链接:https://dev59.com/FV8e5IYBdhLWcg3wS465#29012988 - JustADev

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