Home | History | Annotate | Download | only in recipes
      1 /*
      2  * Copyright (C) 2015 Square, Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.squareup.okhttp.recipes;
     17 
     18 import com.squareup.okhttp.Interceptor;
     19 import com.squareup.okhttp.MediaType;
     20 import com.squareup.okhttp.OkHttpClient;
     21 import com.squareup.okhttp.Response;
     22 import com.squareup.okhttp.ResponseBody;
     23 import com.squareup.okhttp.Request;
     24 import java.io.IOException;
     25 import okio.Buffer;
     26 import okio.BufferedSource;
     27 import okio.ForwardingSource;
     28 import okio.Okio;
     29 import okio.Source;
     30 
     31 public final class Progress {
     32 
     33   private final OkHttpClient client = new OkHttpClient();
     34 
     35   public void run() throws Exception {
     36     Request request = new Request.Builder()
     37         .url("https://publicobject.com/helloworld.txt")
     38         .build();
     39 
     40     final ProgressListener progressListener = new ProgressListener() {
     41       @Override public void update(long bytesRead, long contentLength, boolean done) {
     42         System.out.println(bytesRead);
     43         System.out.println(contentLength);
     44         System.out.println(done);
     45         System.out.format("%d%% done\n", (100 * bytesRead) / contentLength);
     46       }
     47     };
     48 
     49     client.networkInterceptors().add(new Interceptor() {
     50       @Override public Response intercept(Chain chain) throws IOException {
     51         Response originalResponse = chain.proceed(chain.request());
     52         return originalResponse.newBuilder()
     53             .body(new ProgressResponseBody(originalResponse.body(), progressListener))
     54             .build();
     55         }
     56     });
     57 
     58     Response response = client.newCall(request).execute();
     59     if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
     60 
     61     System.out.println(response.body().string());
     62   }
     63 
     64   public static void main(String... args) throws Exception {
     65     new Progress().run();
     66   }
     67 
     68   private static class ProgressResponseBody extends ResponseBody {
     69 
     70     private final ResponseBody responseBody;
     71     private final ProgressListener progressListener;
     72     private BufferedSource bufferedSource;
     73 
     74     public ProgressResponseBody(ResponseBody responseBody, ProgressListener progressListener) {
     75       this.responseBody = responseBody;
     76       this.progressListener = progressListener;
     77     }
     78 
     79     @Override public MediaType contentType() {
     80       return responseBody.contentType();
     81     }
     82 
     83     @Override public long contentLength() throws IOException {
     84       return responseBody.contentLength();
     85     }
     86 
     87     @Override public BufferedSource source() throws IOException {
     88       if (bufferedSource == null) {
     89         bufferedSource = Okio.buffer(source(responseBody.source()));
     90       }
     91       return bufferedSource;
     92     }
     93 
     94     private Source source(Source source) {
     95       return new ForwardingSource(source) {
     96         long totalBytesRead = 0L;
     97         @Override public long read(Buffer sink, long byteCount) throws IOException {
     98           long bytesRead = super.read(sink, byteCount);
     99           // read() returns the number of bytes read, or -1 if this source is exhausted.
    100           totalBytesRead += bytesRead != -1 ? bytesRead : 0;
    101           progressListener.update(totalBytesRead, responseBody.contentLength(), bytesRead == -1);
    102           return bytesRead;
    103         }
    104       };
    105     }
    106   }
    107 
    108   interface ProgressListener {
    109     void update(long bytesRead, long contentLength, boolean done);
    110   }
    111 }
    112