OkHttp3 如何从 http header 检索 Http 内容长度?

OkHttp3 How I can retrieve the Http Content Length from http header?

我尝试下载一个文件,看是否整体下载完毕:


Request request = new Request.Builder().url("http://example.com/myfile.tar.gz").build();
Response response = client.newCall(request).execute();

// Status code checks goes here
if (downloadedTar == null) {
  throw new SettingsFailedException();
}
ResponseBody downloadedTar = response.body();
double contentLength = Double.parseDouble(response.header("content-length"));

File file = File.createTempFile(System.currentTimeMillis()+"_file", ".tar.gz", getContext().getCacheDir());
FileOutputStream download = new FileOutputStream(file);

download.write(downloadedTar.body().bytes());
download.flush();
download.close();

if(file.exists() && (double)file.length() == contentLength){
  // file has been downloaded
}

但是行:

double contentLength = Double.parseDouble(response.header("content-length"));

但是 response.header("content-length") 是 Null 并且没有整数值,我也尝试了以下变体 response.header("Content-Length")response.header("Content-Length") 但没有成功。

那么为什么我无法检索 Content-Length header 以及如何确保文件已成功下载?

Content-Length 在许多情况下被删除,例如 Gzip 响应

https://github.com/square/okhttp/blob/3ad1912f783e108b3d0ad2c4a5b1b89b827e4db9/okhttp/src/jvmMain/kotlin/okhttp3/internal/http/BridgeInterceptor.kt#L98

但通常不能保证流式响应(h2 的分块)存在。

您应该尽量避免要求内容长度,因为它保证存在并且可能会更改。您也可以使用

优化您的 IO

Okio.buffer(Okio.sink(file)).writeAll(response.body().source())

或科特林

file.sink().buffer().writeAll(response.body!!.source())