2016-02-20 9 views
9

Come faccio a monitorare il progresso di caricamento in OkHttp 3 posso trovare risposte per v2, ma non v3, come thisOKHTTP 3 Monitoraggio Multipart caricare il progresso

Una richiesta Multipart campione ricette OkHttp

private static final String IMGUR_CLIENT_ID = "..."; 
private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png"); 

private final OkHttpClient client = new OkHttpClient(); 

public void run() throws Exception { 
    // Use the imgur image upload API as documented at https://api.imgur.com/endpoints/image 
    RequestBody requestBody = new MultipartBody.Builder() 
      .setType(MultipartBody.FORM) 
      .addFormDataPart("title", "Square Logo") 
      .addFormDataPart("image", "logo-square.png", 
        RequestBody.create(MEDIA_TYPE_PNG, new File("website/static/logo-square.png"))) 
      .build(); 

    Request request = new Request.Builder() 
      .header("Authorization", "Client-ID " + IMGUR_CLIENT_ID) 
      .url("https://api.imgur.com/3/image") 
      .post(requestBody) 
      .build(); 

    Response response = client.newCall(request).execute(); 
    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); 

    System.out.println(response.body().string()); 
} 
+0

C'è una ricetta nei campioni 'OkHttp3'. Mostra come mostrare lo stato di avanzamento di un download. Se lo guardi, potresti essere in grado di creare un monitor per il progresso del caricamento. Trovalo qui https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/Progress.java –

risposta

10

È possibile decorare il corpo della richiesta di OkHttp per contare il numero di byte scritti durante la scrittura; per completare questo compito, avvolgi il tuo MultiPart RequestBody in questo RequestBody con un'istanza di Listener e Voila!

public class ProgressRequestBody extends RequestBody { 

    protected RequestBody mDelegate; 
    protected Listener mListener; 
    protected CountingSink mCountingSink; 

    public ProgressRequestBody(RequestBody delegate, Listener listener) { 
     mDelegate = delegate; 
     mListener = listener; 
    } 

    @Override 
    public MediaType contentType() { 
     return mDelegate.contentType(); 
    } 

    @Override 
    public long contentLength() { 
     try { 
      return mDelegate.contentLength(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     return -1; 
    } 

    @Override 
    public void writeTo(BufferedSink sink) throws IOException { 
     mCountingSink = new CountingSink(sink); 
     BufferedSink bufferedSink = Okio.buffer(mCountingSink); 
     mDelegate.writeTo(bufferedSink); 
     bufferedSink.flush(); 
    } 

    protected final class CountingSink extends ForwardingSink { 
     private long bytesWritten = 0; 
     public CountingSink(Sink delegate) { 
      super(delegate); 
     } 
     @Override 
     public void write(Buffer source, long byteCount) throws IOException { 
      super.write(source, byteCount); 
      bytesWritten += byteCount; 
      mListener.onProgress((int) (100F * bytesWritten/contentLength())); 
     } 
    } 

    public interface Listener { 
     void onProgress(int progress); 
    } 
} 

Verificare this link per ulteriori informazioni.

+1

@Saurabh il metodo write() viene chiamato più volte su un rete lenta a volte. Quindi il% effettivo supera il 100%. Hai riscontrato questo problema? – geekoraul

+0

Non proprio, cosa intendi per "più volte"? Quante volte? 3-4 o 40-60? – Sourabh

+0

Beh, non è un numero fisso di volte, come ho detto, dipende dalla rete. Quindi diciamo che la percentuale totale raggiunge a volte il 115% e talvolta raggiunge il 400%. La domanda è che hai riscontrato questo comportamento? – geekoraul

0

Secondo la risposta di Sourabh, voglio dire a quel campo di CountingSink

private long bytesWritten = 0; 

deve essere spostato in ProgressRequestBody classe

+0

Perché, hai riscontrato bug quando si trovava nella classe 'CountingSink'? – Sourabh

+0

Ho testato questo codice su Android. Percentuale in arrivo da Listener.onProgress() era nell'ordine errato: 0, 1, 2, 0, 1, 2 e quindi ho ottenuto questa eccezione: java.net.SocketException: sendto non riuscito: ECONNRESET (Connessione ripristinata da peer) Causato da android.system.ErrnoException: sendto non riuscito: ECONNRESET ECONNRESET (Connessione ripristinata dal peer) –