7

I need to download image from server and save it to folder, so I am using Retrofit 2.

Problem is that saved images is empty when I look for it in folder and I tried to debug and saw that Bitmap is null.

I do not get why, here is my code:

@GET("images/{userId}/{imageName}")
@Streaming
Call<ResponseBody> downloadImage(@Path("userId") String userId, @Path("imageName") String imageName);

Download image code:

 private void downloadImage(final int position) {
    String url = "htttp://myserver.com/";
        retrofitImage = new Retrofit.Builder()
                .baseUrl(url)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

    imageApi = retrofitImage.create(BlastApiService.class);

    String userId = feedList.get(position).getUserId();
    String fileName = feedList.get(position).getFile();

    Call<ResponseBody> imageCall = imageApi.downloadImage(userId, fileName );
    imageCall.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            if(response.isSuccess()){
                String fileName = feedList.get(position).getFile();
                InputStream is = response.body().byteStream();
                Bitmap bitmap = BitmapFactory.decodeStream(is);
                saveImage1(bitmap, fileName);
            } else{
                try {
                    Log.d("TAG", "response error: "+response.errorBody().string().toString());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
            Log.d("TAG", "Image download error: " + t.getLocalizedMessage());
        }
    });

}

Here is method to save image.

 private void saveImage1(Bitmap imageToSave, String fileName) {
    // get the path to sdcard
    File sdcard = Environment.getExternalStorageDirectory();
    // to this path add a new directory path
    File dir = new File(sdcard.getAbsolutePath() + "/FOLDER_NAME/");
    // create this directory if not already created
    dir.mkdir();
    // create the file in which we will write the contents
    File file = new File(dir, fileName);
    try {
        FileOutputStream out = new FileOutputStream(file);
        imageToSave.compress(Bitmap.CompressFormat.JPEG, 100, out);
        out.flush();
        out.close();
        counter++;
       // if (counter < feedList.size()) {
            //downloadImage(counter);
        //} else {
            setImage();
        //}
    } catch (Exception e) {
        e.printStackTrace();
    }
}
Zookey
  • 2,637
  • 13
  • 46
  • 80
  • Why are you not using a dedicated ImageLoader, say Glide or UIL? Just curious and trying to get some background to the problem. – Elvis Chweya Feb 20 '16 at 11:46
  • String url = "htttp://myserver.com/"; is wrong! 3 t in htttp. – Loghman Mohamadzadeh Feb 20 '16 at 12:50
  • @ElvisChweya Client wants that I download images to folder and then to display from local folder instead of using image loading from server directly. Because the app has only one image view and API returns me 10 images, so client do not want to user wait a few seconds to display image from server (1 to 2 MB images). – Zookey Feb 20 '16 at 15:14
  • @Zookey, but that is what imageloaders do. They only download the image once and store on sdcard, then consecutive calls to load are simply loaded from storage/sdcard. Plus, they do memory caching and update image when they are updated server-side. – Elvis Chweya Feb 20 '16 at 15:26
  • But say you are still needed to just download the images then load then from storage, Glide can be used to download the images only. Using retrofit for this is unnecessary. Please don't use Retrofit for image loading. The benefits of using Glide to load even images stored in storage are huge. – Elvis Chweya Feb 20 '16 at 15:32
  • I know what are image loaders and what they do, but client thinks that better solution is to download all images, and then show them instantly. He do not want to listen to my suggestion to use image loaders. Weird, I know. So, I thought to download images with Retrofit and then use some image loading lib to display images from folder. – Zookey Feb 20 '16 at 16:22
  • @Zookey I am also facing same problem now. Did you met with any solution back then. – Dilip Poudel Mar 07 '18 at 10:03

2 Answers2

2

This worked for me:

public static boolean writeResponseBody(ResponseBody body, String path) {
    try {

        File file = new File(path);

        InputStream inputStream = null;
        OutputStream outputStream = null;

        try {
            byte[] fileReader = new byte[4096];
            //long fileSize = body.contentLength();
            //long fileSizeDownloaded = 0;

            inputStream = body.byteStream();
            outputStream = new FileOutputStream(file);

            while (true) {
                int read = inputStream.read(fileReader);

                if (read == -1) {
                    break;
                }
                outputStream.write(fileReader, 0, read);
                //fileSizeDownloaded += read;
            }

            outputStream.flush();

            return true;
        } catch (IOException e) {
            return false;
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }

            if (outputStream != null) {
                outputStream.close();
            }
        }
    } catch (IOException e) {
        return false;
    }
}

after call this method you can get image from path:

boolean result = writeResponseBody(body, path);
if(result) {
    Bitmap bitmap = BitmapFactory.decodeFile(path)
}
David
  • 2,129
  • 25
  • 34
0
private boolean writeResponseBodyToDisk(ResponseBody body, String name) {
    try {
        String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString() + "/MyApp";
        File dir = new File(path);
        if (!dir.exists())
            dir.mkdirs();


        File futureStudioIconFile = new File(path, name + ".pdf");//am saving pdf file
        if (futureStudioIconFile.exists())
            futureStudioIconFile.delete();
        futureStudioIconFile.createNewFile();


        InputStream inputStream = null;
        OutputStream outputStream = null;

        try {
            byte[] fileReader = new byte[4096];

            long fileSize = body.contentLength();
            long fileSizeDownloaded = 0;

            inputStream = body.byteStream();
            outputStream = new FileOutputStream(futureStudioIconFile);

            while (true) {
                int read = inputStream.read(fileReader);

                if (read == -1) {
                    break;
                }

                outputStream.write(fileReader, 0, read);

                fileSizeDownloaded += read;
            }

            outputStream.flush();

            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }

            if (outputStream != null) {
                outputStream.close();
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    }
}
Muhamed El-Banna
  • 593
  • 7
  • 21