我希望能够在使用 OkHttp 获取内容时记录 Web 服务器响应主体的实际大小(用于监控目的)。
有没有一种方法可以获得响应主体的实际大小(注意 - 不是服务器声明的内容长度)而不需要将整个响应缓冲到内存中?
最佳答案
这似乎对我想要的有用......
AtomicLong bytesRead = new AtomicLong();
OkHttpClient client = new OkHttpClient.Builder().addNetworkInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
response = response.newBuilder()
.body(
new RealResponseBody(
response.body().contentType().toString(),
response.body().contentLength(),
Okio.buffer(
new LengthTrackingSource(
response.body().source(),
(newBytesRead) -> {
bytesRead.addAndGet(newBytesRead);
}
)
)
)
)
.build();
return response;
}
class LengthTrackingSource implements Source {
private Source source;
private Consumer<Long> lengthRecorder;
public LengthTrackingSource(Source source, Consumer<Long> lengthRecorder) {
this.source = source;
this.lengthRecorder = lengthRecorder;
}
@Override
public long read(Buffer sink, long byteCount) throws IOException {
long bytesRead;
try {
bytesRead = source.read(sink, byteCount);
} catch (IOException e) {
throw e;
}
// Avoid adding the final -1 (which means the source is exhausted)
if (bytesRead > 0) {
lengthRecorder.accept(bytesRead);
}
return bytesRead;
}
@Override
public Timeout timeout() {
return source.timeout();
}
@Override
public void close() throws IOException {
source.close();
}
}
}).build();
try (Response response = client.newCall(new Request.Builder().url("http://example.com/").build()).execute()) {
System.out.println(bytesRead.get());
String body = response.body().string();
System.out.println(body.length());
System.out.println(bytesRead.get());
}
如果有更简单的方法,我仍然很想听听!
关于java - 在不缓冲整个事情的情况下记录 OkHttp 响应主体大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47386132/