2016-04-24 15 views
6

Sto tentando di modificare la libreria open source di cloudinary in modo che possa ascoltare l'avanzamento del caricamento della mia foto. La classe della libreria contiene una classe java MultipartUtility che ho modificato per ascoltare l'avanzamento del caricamento.Android: caricamento di una foto in Cloudinary con callback di avanzamento in HttpURLConnection

Il codice originale prima modifiche può essere trovato su github: https://github.com/cloudinary/cloudinary_java/blob/master/cloudinary-android/src/main/java/com/cloudinary/android/MultipartUtility.java

ho letteralmente modificato per assomigliare il codice da un altro CloudFS di servizi cloud che supporta il progresso durante il caricamento di file/immagini ecc:

https://github.com/bitcasa/CloudFS-Android/blob/master/app/src/main/java/com/bitcasa/cloudfs/api/MultipartUpload.java

Le modifiche apportate dovevano aggiungere quanto segue alla httpURLConnection come consigliato da questo thread: How to implement file upload progress bar in android: httpConn.setFixedLengthStreamingMode(filesize);

Poi ho creato una semplice interfaccia per ascoltare l'avanzamento del caricamento:

public interface UploadingCallback { 

    void uploadListener(int progress); 

} 

E poi ho attaccato mentre la HttpURLConnection ha scritto la foto:

 while ((bytesRead = inputStream.read(buffer)) != -1) { 
      outputStream.write(buffer, 0, bytesRead); 
      progress += bytesRead; 
/*   int percentage = ((progress/filesize.intValue()) * 100);*/ 
      if (uploadingCallback != null) { 
       uploadingCallback.uploadListener(progress); 
      } 

     } 

Il codice ha funzionato ma i progressi del caricamento non sembra essere stato misurato correttamente. La foto era di circa 365kb e il caricamento è durato circa un decimo di secondo (ho iniziato il caricamento a 17: 56: 55.481 e per 17: 56: 55.554 è stato fatto, questo è poco più di 0.7 secondi). Non credo che la mia connessione internet sia così veloce e aspetto che ci voglia almeno 5 secondi. Ho la sensazione che stia misurando il tempo impiegato per scrivere la foto sul buffer invece del tempo impiegato per inviarlo ai server di cloudinary.

Come posso misurare il tempo necessario per caricare la foto in modo da poter utilizzare i dati per la barra di avanzamento?

04-24 17:56:55.481 28306-28725/com.a upload 4096 
04-24 17:56:55.486 28306-28725/com.a upload 8192 
04-24 17:56:55.486 28306-28725/com.a upload 12288 
04-24 17:56:55.486 28306-28725/com.a upload 16384 
04-24 17:56:55.487 28306-28725/com.a upload 20480 
04-24 17:56:55.487 28306-28725/com.a upload 24576 
04-24 17:56:55.487 28306-28725/com.a upload 28672 
04-24 17:56:55.487 28306-28725/com.a upload 32768 
04-24 17:56:55.491 28306-28725/com.a upload 36864 
04-24 17:56:55.492 28306-28725/com.a upload 40960 
04-24 17:56:55.493 28306-28725/com.a upload 45056 
04-24 17:56:55.493 28306-28725/com.a upload 49152 
04-24 17:56:55.493 28306-28725/com.a upload 53248 
04-24 17:56:55.493 28306-28725/com.a upload 57344 
04-24 17:56:55.494 28306-28725/com.a upload 61440 
04-24 17:56:55.494 28306-28725/com.a upload 65536 
04-24 17:56:55.494 28306-28725/com.a upload 69632 
04-24 17:56:55.494 28306-28725/com.a upload 73728 
04-24 17:56:55.494 28306-28725/com.a upload 77824 
04-24 17:56:55.495 28306-28725/com.a upload 81920 
04-24 17:56:55.495 28306-28725/com.a upload 86016 
04-24 17:56:55.495 28306-28725/com.a upload 90112 
04-24 17:56:55.495 28306-28725/com.a upload 94208 
04-24 17:56:55.495 28306-28725/com.a upload 98304 
04-24 17:56:55.495 28306-28725/com.a upload 102400 
04-24 17:56:55.495 28306-28725/com.a upload 106496 
04-24 17:56:55.496 28306-28725/com.a upload 110592 
04-24 17:56:55.496 28306-28725/com.a upload 114688 
04-24 17:56:55.496 28306-28725/com.a upload 118784 
04-24 17:56:55.497 28306-28725/com.a upload 122880 
04-24 17:56:55.498 28306-28725/com.a upload 126976 
04-24 17:56:55.498 28306-28725/com.a upload 131072 
04-24 17:56:55.498 28306-28725/com.a upload 135168 
04-24 17:56:55.498 28306-28725/com.a upload 139264 
04-24 17:56:55.499 28306-28725/com.a upload 143360 
04-24 17:56:55.506 28306-28725/com.a upload 147456 
04-24 17:56:55.510 28306-28725/com.a upload 151552 
04-24 17:56:55.510 28306-28725/com.a upload 155648 
04-24 17:56:55.514 28306-28725/com.a upload 159744 
04-24 17:56:55.515 28306-28725/com.a upload 163840 
04-24 17:56:55.517 28306-28725/com.a upload 167936 
04-24 17:56:55.517 28306-28725/com.a upload 172032 
04-24 17:56:55.518 28306-28725/com.a upload 176128 
04-24 17:56:55.518 28306-28725/com.a upload 180224 
04-24 17:56:55.518 28306-28725/com.a upload 184320 
04-24 17:56:55.519 28306-28725/com.a upload 188416 
04-24 17:56:55.519 28306-28725/com.a upload 192512 
04-24 17:56:55.519 28306-28725/com.a upload 196608 
04-24 17:56:55.519 28306-28725/com.a upload 200704 
04-24 17:56:55.520 28306-28725/com.a upload 204800 
04-24 17:56:55.525 28306-28725/com.a upload 208896 
04-24 17:56:55.526 28306-28725/com.a upload 212992 
04-24 17:56:55.527 28306-28725/com.a upload 217088 
04-24 17:56:55.530 28306-28725/com.a upload 221184 
04-24 17:56:55.530 28306-28725/com.a upload 225280 
04-24 17:56:55.530 28306-28725/com.a upload 229376 
04-24 17:56:55.530 28306-28725/com.a upload 233472 
04-24 17:56:55.530 28306-28725/com.a upload 237568 
04-24 17:56:55.531 28306-28725/com.a upload 241664 
04-24 17:56:55.532 28306-28725/com.a upload 245760 
04-24 17:56:55.532 28306-28725/com.a upload 249856 
04-24 17:56:55.532 28306-28725/com.a upload 253952 
04-24 17:56:55.533 28306-28725/com.a upload 258048 
04-24 17:56:55.533 28306-28725/com.a upload 262144 
04-24 17:56:55.535 28306-28725/com.a upload 266240 
04-24 17:56:55.540 28306-28725/com.a upload 270336 
04-24 17:56:55.540 28306-28725/com.a upload 274432 
04-24 17:56:55.541 28306-28725/com.a upload 278528 
04-24 17:56:55.541 28306-28725/com.a upload 282624 
04-24 17:56:55.543 28306-28725/com.a upload 286720 
04-24 17:56:55.545 28306-28725/com.a upload 290816 
04-24 17:56:55.545 28306-28725/com.a upload 294912 
04-24 17:56:55.547 28306-28725/com.a upload 299008 
04-24 17:56:55.547 28306-28725/com.a upload 303104 
04-24 17:56:55.547 28306-28725/com.a upload 307200 
04-24 17:56:55.547 28306-28725/com.a upload 311296 
04-24 17:56:55.547 28306-28725/com.a upload 315392 
04-24 17:56:55.548 28306-28725/com.a upload 319488 
04-24 17:56:55.548 28306-28725/com.a upload 323584 
04-24 17:56:55.548 28306-28725/com.a upload 327680 
04-24 17:56:55.548 28306-28725/com.a upload 331776 
04-24 17:56:55.549 28306-28725/com.a upload 335872 
04-24 17:56:55.549 28306-28725/com.a upload 339968 
04-24 17:56:55.549 28306-28725/com.a upload 344064 
04-24 17:56:55.550 28306-28725/com.a upload 348160 
04-24 17:56:55.550 28306-28725/com.a upload 352256 
04-24 17:56:55.551 28306-28725/com.a upload 356352 
04-24 17:56:55.551 28306-28725/com.a upload 360448 
04-24 17:56:55.552 28306-28725/com.a upload 364544 
04-24 17:56:55.554 28306-28725/com.a upload 365790 

per testare questo per voi stessi, è necessario creare un account gratuito sul sito cloudinary al fine di ottenere il vostro cloudname in modo da poter collegare lo SDK di Android per i loro servizi per un upload diretto non firmato da Android direttamente a i loro server.

EDIT:

Questo è quello che ho provato e salta ancora 0-100% a 0,7 secondi quando il caricamento in realtà finisce nel tempo di 7 secondi:

while ((bytesRead = inputStream.read(buffer)) != -1) { 
     outputStream.write(buffer, 0, bytesRead); 
     progress += bytesRead; 
     Log.d("MultiPart", "file transferred so far: " 
       + progress); 
     if (uploadingCallback != null) { 
      uploadingCallback.uploadListener(progress); 
     } 
     Log.d("Flushing", "flush the writer"); 
     outputStream.flush(); 
     writer.flush(); 
    } 

risposta

3

C'è un problema nell'uso del metodo flush() e nel momento in cui si chiama update callback().

Come puoi vedere dal tuo codice ogni volta che leggi parte dell'immagine, la scrivi sul buffer di output, ma ciò non significa che sia inviata al server, potrebbe essere memorizzata nel buffer, e successivamente in scrittura ' n al server.

Avete due opzioni, chiamate outputStream.flush() dopo ogni outputStream.write(), ma questo ucciderà le prestazioni del caricamento, perché si perderebbero i vantaggi del buffering.

Oppure puoi chiamare il tuo updateCallback() dopo outputStream.flush() alla fine del tuo metodo. Perché dopo outputStream.flush() si è certi che i dati siano sul server e che il progresso sia finito.

Per maggiori informazioni sul filo vedere questa discussione What is the purpose of flush() in Java streams?

+0

La seconda alternativa rende molto poco senso perché sarebbe anche essere al 100% e l'intero scopo di quello che sto cercando di fare è quello di ottenere un indicatore di progresso per il caricare. Ho provato la tua prima alternativa e non sembra funzionare, ho inserito una modifica per mostrare che vuoi aver provato. – Simon

+0

Bene che devi fare qualcosa come l'ug__ proporrà. Dovresti chiamare flush() una volta ogni tanto :), ma come posso vedere dal tuo cambiamento, anche questo non funziona per te. Dovrò testarlo e farti sapere, ma sono sicuro al 99% che chiamare flush() sia la strada giusta da percorrere. Forse c'è qualche problema in qualche altra parte del tuo codice. Avrà bisogno di testare questo, che farò subito. – aleksamarkoni

+0

Tecnicamente, il richiamo di flush su outputstream non farà nulla in quanto i documenti dicono che non fa nulla: https://docs.oracle.com/javase/7/docs/api/java/io/OutputStream.html#flush() I ' m gettandolo su DataOutputStream per vedere se farà la differenza ora. In realtà non fa differenza. – Simon

0

Questo è un salto nel buio perché non ho testato su un ambiente Android, tuttavia vi consiglierei di provare il seguente.

Invece di utilizzare un utilizzo lunghezza fissa setChunkedStreamingMode

//httpConn.setFixedLengthStreamingMode(filesize); 
httpConn.setChunkedStreamingMode(4096); // or whatever size you see fit 

fare questo dovrebbe parte grilletto della richiesta di ottenere inviato ogni volta che si invia a 4096 byte di dati e di sostanza, stanare il buffer interno.


Si potrebbe anche provare il lavaggio manuale del buffer dopo ogni scrittura, questo potrebbe rallentare il caricamento di file, soprattutto se si filo spesso però si sarebbe probabilmente risolvere il problema. Potresti finire a giocare con le dimensioni del buffer per trovare un punto debole.

while ((bytesRead = inputStream.read(buffer)) != -1) { 
    outputStream.write(buffer, 0, bytesRead); 
    progress += bytesRead; 
    /* int percentage = ((progress/filesize.intValue()) * 100);*/ 
    if (uploadingCallback != null) { 
     uploadingCallback.uploadListener(progress); 
    } 
    // trigger the stream to write its data 
    outputStream.flush(); 
} 

Con una di queste modifiche si sarebbe probabilmente vuole permettere all'utente di scegliere di impostare la propria dimensione del buffer invece di passare nella dimensione totale del file. EG cambiare il vostro costruttore al seguente:

MultipartUtility(String requestURL, String charset, 
       String boundary, Map<String, String> headers, int chunkSize) 
+0

Sono un po 'nervoso sull'uso di setChunkedStreamingMode mentre leggo nei documenti che: I vecchi server HTTP/1.0 non supportano questa modalità. Non so che tipo di server cloudinario stia usando, quindi potrebbe non funzionare. La modalità fixedlengthstreaming non sembra avere questa restrizione. Ad ogni modo, ho provato anche i tuoi suggerimenti per il colore e non sembra funzionare. Vedi modifica nella mia domanda per vedere cosa ho provato. – Simon

+0

@Simon La documentazione afferma che l'implementazione URLConnection è progettata per RFC 2616 che è l'HTTP/1.1 specifica, sarei molto sorpreso se il server che stai cercando di connettersi non supporta quella specifica in quanto è uno standard sul web in questi giorni. Sto guardando la prima frase di http://developer.android.com/reference/java/net/HttpURLConnection.html –

Problemi correlati