2014-06-11 14 views
7

używam Retrofit 1.6.0 na moim Android projektuZastosowanie modernizacyjny pobrać plik obrazu

URL żądania:

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

Mój interfejs tak:

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

HTTP Żądanie zakończyło się sukcesem, ale wystąpił błąd:

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 

Jak rozwiązać ten problem?

+0

może zajrzeć do http: //square.github.io/picasso/ czyli biblioteka pobierania obrazów utworzona przez kwadrat. w przeciwnym razie powinieneś zajrzeć do pliku TypedFile na temat retrofitu http://square.github.io/retrofit/javadoc/index.html – Aegis

+0

Mam inne interfejsy API do modernizacji, jeśli trzeba załadować, aby zobaczyć mayebe Użyję picasso, dzięki za twoją sugestię ! –

Odpowiedz

8

Problem jest nagłówek Content-Type na odpowiedź zawiera fałszywe charset:

Content-Type: image/png; charset=binary 

Modernizacja widzi to i wnioskuje, że odpowiedź jest tekst, który może się zalogować. Powinieneś zgłosić problem administratorowi serwera.

Jeśli zgłosisz problem do modułu śledzenia problemów Retrofit na GitHub, prawdopodobnie uda się rozwiązać problem, zamiast się zawiesić.

+0

Dzięki! usuń po stronie serwera "charset = binary", działa! –

1

Innym sposobem jest wyłączenie pełne rejestrowanie, więc retrofit.RestAdapter.logAndReplaceResponse nie będzie starał się konsumować treści odpowiedzi

2

Oczywiście zazwyczaj używamy Picasso załadować obraz, ale czasami naprawdę musimy użyć do Retrofit załaduj specjalny obraz (np. pobierz obraz captcha), dodaj nagłówek dla zapytania, zdobądź trochę wartości z nagłówka odpowiedzi (oczywiście możesz również użyć Picassa + OkHttp, ale w projekcie, którego już używasz Retrofit do obsługi większości zapytań netto), więc poniżej przedstawiamy, jak wdrożyć przez Retrofit 2.0.0 (już zaimplementowałem w moim projekcie).

Najważniejsze jest to, że aby uzyskać odpowiedź, musisz użyć okhttp3.ResponseBody, w przeciwnym razie Retrofit przeanalizuje dane odpowiedzi jako JSON, a nie dane binarne.

kody:

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

gram z rxjava i modernizowanych te dni, mam tutaj na szybkie demo. Talk jest tani, pokaż mój kod bezpośrednio, mam nadzieję, że to pomaga.

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

i napisałem własną BitmapConverterFactory konwertować strumień bajtów do bitmapy:

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 Zależności tutaj:

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

Wiwaty, vanvency