2014-06-11 17 views
7

Io uso Retrofit 1.6.0 sul mio progetto Android,Usa retrofit per scaricare il file immagine

richiesta url:

https://example.com/image/thumbs/filename/sample.png

mia interfaccia come questa:

public interface ImageService { 
    @GET("/image/thumbs/filename/{filename}") 
    @Streaming 
    void getThumbs(
     @Path("filename") String filename, 
     Callback<Response> callback 
    ); 
} 

HTTP la richiesta è andata a buon fine, ma si verificano alcuni errori

D/Retrofit(27613): ---> HTTP GET https://example.com/image/thumbs/filename/sample.png 
D/Retrofit(27613): ---> END HTTP (no body) 
D/Retrofit(27613): <--- HTTP 200 https://example.com/image/thumbs/filename/sample.png (451ms) 
D/Retrofit(27613): : HTTP/1.1 200 OK 
D/Retrofit(27613): Connection: Keep-Alive 
D/Retrofit(27613): Content-Disposition: inline; filename="sample.png" 
D/Retrofit(27613): Content-Type: image/png; charset=binary 
D/Retrofit(27613): Date: Wed, 11 Jun 2014 06:02:31 GMT 
D/Retrofit(27613): Keep-Alive: timeout=5, max=100 
D/Retrofit(27613): OkHttp-Received-Millis: 1402466577134 
D/Retrofit(27613): OkHttp-Response-Source: NETWORK 200 
D/Retrofit(27613): OkHttp-Sent-Millis: 1402466577027 
D/Retrofit(27613): Server: Apache/2.2.22 (Ubuntu) 
D/Retrofit(27613): Transfer-Encoding: chunked 
D/Retrofit(27613): X-Powered-By: PHP/5.4.28-1+deb.sury.org~precise+1 
D/Retrofit(27613): ---- ERROR https://example.com/image/thumbs/filename/sample.png 
D/Retrofit(27613): java.io.UnsupportedEncodingException: binary 
D/Retrofit(27613):  at java.nio.charset.Charset.forNameUEE(Charset.java:322) 
D/Retrofit(27613):  at java.lang.String.<init>(String.java:228) 
D/Retrofit(27613):  at retrofit.RestAdapter.logAndReplaceResponse(RestAdapter.java:478) 
D/Retrofit(27613):  at retrofit.RestAdapter.access$500(RestAdapter.java:109) 
D/Retrofit(27613):  at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:333) 
D/Retrofit(27613):  at retrofit.RestAdapter$RestHandler.access$100(RestAdapter.java:220) 
D/Retrofit(27613):  at retrofit.RestAdapter$RestHandler$2.obtainResponse(RestAdapter.java:278) 
D/Retrofit(27613):  at retrofit.CallbackRunnable.run(CallbackRunnable.java:42) 
D/Retrofit(27613):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
D/Retrofit(27613):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
D/Retrofit(27613):  at retrofit.Platform$Android$2$1.run(Platform.java:142) 
D/Retrofit(27613):  at java.lang.Thread.run(Thread.java:841) 
D/Retrofit(27613): Caused by: java.nio.charset.UnsupportedCharsetException: binary 
D/Retrofit(27613):  at java.nio.charset.Charset.forName(Charset.java:309) 
D/Retrofit(27613):  at java.nio.charset.Charset.forNameUEE(Charset.java:320) 
D/Retrofit(27613):  ... 11 more 
D/Retrofit(27613): ---- END ERROR 

Come posso risolvere questo problema?

+0

forse guardare in http: //square.github.io/picasso/ che è una libreria di download di immagini creata anche da square. altrimenti dovresti cercare su TypedFile sul retrofit http://square.github.io/retrofit/javadoc/index.html – Aegis

+0

Ho altre API che usano il retrofit, se è necessario caricare per visualizzare mayebe userò picasso, grazie per il tuo suggerimento ! –

risposta

8

Il problema è il tipo di contenuto intestazione sulla risposta include un set di caratteri fasullo:

Content-Type: image/png; charset=binary 

Retrofit vede questo e ne deduce che la risposta è un testo che si può accedere. È necessario segnalare il problema all'amministratore del server.

Se si segnala il problema al tracker dei problemi di Retrofit su GitHub, è probabile che possiamo riprenderci da questo problema piuttosto che dall'arresto anomalo.

+0

Grazie! lato server rimuovere "charset = binario", funziona! –

1

Un altro modo è quello di spegnere la registrazione completa, in modo che il retrofit.RestAdapter.logAndReplaceResponse non cercherà di consumare il corpo della risposta

2

Naturalmente usiamo di solito Picasso per caricare un'immagine, ma a volte abbiamo davvero bisogno usare Retrofit per caricare un'immagine speciale (come recuperare un'immagine captcha), è necessario aggiungere un'intestazione per la richiesta, ottenere un valore dall'intestazione di risposta (ovviamente è possibile utilizzare anche Picasso + OkHttp, ma in un progetto è già stato utilizzato Retrofit per gestire la maggior parte delle richieste nette), ecco quindi come implementare Retrofit 2.0.0 (che ho già implementato nel mio progetto).

Il punto chiave è che è necessario utilizzare okhttp3.ResponseBody per ricevere risposta, altrimenti Retrofit analizzerà i dati di risposta come JSON, non i dati binari.

codici:

public interface Api { 
    // don't need add 'Content-Type' header, it not works for Retrofit 2.0.0 
    // @Headers({"Content-Type: image/png"}) 
    @GET 
    Call<ResponseBody> fetchCaptcha(@Url String url); 
} 

Call<ResponseBody> call = api.fetchCaptcha(url); 
call.enqueue(new Callback<ResponseBody>() { 
     @Override 
     public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { 
      if (response.isSuccessful()) { 
       if (response.body() != null) { 
        // display the image data in a ImageView or save it 
        Bitmap bm = BitmapFactory.decodeStream(response.body().byteStream()); 
        ivCaptcha.setImageBitmap(bm); 
       } else { 
        // TODO 
       } 
      } else { 
       // TODO 
      } 
     } 

     @Override 
     public void onFailure(Call<ResponseBody> call, Throwable t) { 
      // TODO 
     } 
    }); 
4

sto giocando con rxjava e Retrofit in questi giorni, ho una demo veloce qui. Talk è economico, mostra il mio codice direttamente, spero che sia d'aiuto.

public interface ImageService { 

    String ENDPOINT = "HTTP://REPLACE.ME"; 

    @GET 
    @Streaming 
    Observable<Bitmap> getThumbs(@Url String filepath); 

    /******** 
    * Helper class that sets up a new services 
    *******/ 
    class Instance { 

     static ImageService instance; 

     public static ImageService get() { 
      if (instance == null) 
       instance = newImageService(); 
      return instance; 
     } 

     public static ImageService newImageService() { 
      Retrofit retrofit = new Retrofit.Builder() 
        .baseUrl(ImageService.ENDPOINT) 
        .addConverterFactory(BitmapConverterFactory.create()) 
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
        .build(); 
      return retrofit.create(ImageService.class); 
     } 
    } 
} 

e ho scritto il mio BitmapConverterFactory per convertire flusso di byte di bitmap:

public final class BitmapConverterFactory extends Converter.Factory { 

    public static BitmapConverterFactory create() { 
     return new BitmapConverterFactory(); 
    } 


    private BitmapConverterFactory() { 
    } 

    @Override 
    public Converter<ResponseBody, Bitmap> responseBodyConverter(Type type, Annotation[] annotations, 
                   Retrofit retrofit) { 
     if (type == Bitmap.class) { 
      return new Converter<ResponseBody, Bitmap>(){ 

       @Override 
       public Bitmap convert(ResponseBody value) throws IOException { 
        return BitmapFactory.decodeStream(value.byteStream()); 
       } 
      }; 
     } else { 
      return null; 
     } 
    } 

    @Override 
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] annotations, 
                  Retrofit retrofit) { 
     return null; 
    } 
} 

Gradle dipendenze qui:

final RETROFIT_VERSION = '2.0.0-beta3' 
compile "com.squareup.retrofit2:retrofit:$RETROFIT_VERSION" 
compile "com.squareup.retrofit2:adapter-rxjava:$RETROFIT_VERSION" 

Cheers, vanvency

Problemi correlati