java - 在不缓冲整个事情的情况下记录 OkHttp 响应主体大小

标签 java okhttp

我希望能够在使用 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/

相关文章:

java - 字符串中字节的十六进制表示

java - Android http 连接 OkHttp 不工作

web-services - kotlin 中的 HTTP GET 请求

android - 从 Android 中的文件加载 SVG

java - okhttp 中的代理问题

java - OkHttp 是否支持接受自签名 SSL 证书?

java - 如何在 collect 的 java 流中将 Map<String, Person> 转换为 Map<String, Integer>?

java - 安卓日志类

java - xml解析问题

java - 如何从显示中删除字符串