Use retrofit to download image file

后端 未结 4 948
一个人的身影
一个人的身影 2020-12-10 07:06

I use Retrofit 1.6.0 on my Android project,

the request url:

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

My interface like this:

<         


        
相关标签:
4条回答
  • 2020-12-10 07:23

    Another way is to turn off full logging, so the retrofit.RestAdapter.logAndReplaceResponse will not try to consume the response body

    0 讨论(0)
  • 2020-12-10 07:34

    Of course we usually use Picasso to load image, but sometimes we really need use Retrofit to load a special image (like fetch a captcha image), you need add some header for request, get some value from header of response (of course you can also use Picasso + OkHttp, but in a project you have already use Retrofit to handle most of net requests), so here introduce how to implement by Retrofit 2.0.0 (I have already implemented in my project).

    The key point is that you need use okhttp3.ResponseBody to receive response, else Retrofit will parse the response data as JSON, not binary data.

    codes:

    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
            }
        });
    
    0 讨论(0)
  • 2020-12-10 07:38

    I am playing with rxjava and retrofit these days, I have a quick demo here. Talk is cheap, show you my code directly, hope it helps.

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

    And I wrote my own BitmapConverterFactory to convert byte stream to 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 dependencies here:

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

    Cheers, vanvency

    0 讨论(0)
  • 2020-12-10 07:44

    The issue is the content-type header on the response includes a bogus charset:

    Content-Type: image/png; charset=binary
    

    Retrofit sees this and infers that the response is text that it can log. You should report the problem to the server's administrator.

    If you report the issue to Retrofit's issue tracker on GitHub, we can probably recover from this problem rather than crashing.

    0 讨论(0)
提交回复
热议问题