2017-11-20 16 views
0

私は監視目的でOkHttpを使って物事を取得するときに、Webサーバレスポンスボディの実際のサイズを記録できるようにします。全体をバッファリングせずにOkHttpレスポンスボディサイズを記録する

レスポンスボディの実際のサイズを取得する方法はありますか(メモ - サーバーが要求したコンテンツ長ではありません)、応答全体をメモリにバッファリングする必要はありませんか?

+0

しかし、サーバーはcontentLengthについて正しいですよね?この文書をチェックしてください:https://square.github.io/okhttp/3.x/okhttp/okhttp3/ResponseBody.html – rafid059

+0

まあ、コンテンツの長さがコンテンツのどこかからストリーミングされているため不確定な長さ(つまり、ResponseBody.contentLengthが-1を返す場合)...しかし、それは必ずしも私のサーバではなく、おそらく誤った長さのヘッダを返すかもしれません(おそらくokhttpはそれをどうにかして禁止します)。 –

+0

ああ、まだ適切には消化していませんが、https://gist.github.com/digitalbuddha/3c5bb15fa12a553c85ecのreadTwiceのように見えます(2番目の読み取りはちょうど長さを数える実際のコンテンツは無視されます)。 –

答えて

0

これは私が望んでいた何のために働くようで...

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()); 
} 

私はまだそれについて聞いてみたい簡単な方法があります場合は!

関連する問題