Retrofit: Downloading File Using Retrofit, Download incomplete - close to actual file size.

Created on 24 Oct 2015  路  8Comments  路  Source: square/retrofit

I am using retrofit to download a file (any size - Tried 10MB, 50MB ) but it is partially downloaded in my android application. I have seen same sort of issue for the file uploading.

I can see that the file is downloaded, In the log, it prints,

read: Unexpected EOF!

This is the only visible indication that I can see on the logs for this issue.

and even after this print I can see more logs related to download (I think downloading happens even after this read: Unexpected EOF! ).

This is the Retrofit code,

 @GET("/resource/downloadApk")
Observable<Response> downloadAPK(@Query("packageName") String packageName, @Query("versionCode") Integer versionCode);

public RestController getRestController(){
    restAdapter = new RestAdapter.Builder()
            .setEndpoint(URL)
            .setRequestInterceptor(cookieHeaderProvider)
            .setLogLevel(RestAdapter.LogLevel.FULL)
           /* .setErrorHandler(new RetrofitErrorHandler())*/
            .build();
    return  restAdapter.create(RestController.class);

I am using this code to do the download,

Response response = BlockingObservable.from(responseObservable).first();

    String pathToApkFolder = context.getExternalFilesDir(null) + File.separator + "File_name' + ".apk";

    File targetFile = new File(pathToApkFolder);
    targetFile.deleteOnExit();
    try {
        if (response.getStatus() == 200) {
            InputStream inputStream = null;
            OutputStream outputStream = null;

            try {
                inputStream = response.getBody().in();
                byte[] buff = new byte[4096];
                long downloaded = 0;
                long target = response.getBody().length();

                Log.wtf(TAG, "File size is: " + Long.toString(target));
                publishProgress(0L, target);
                OutputStream outStream = new FileOutputStream(targetFile);
                while (true) {

                    int read = inputStream.read(buff);
                    if (read == -1) {
                        break;
                    }
                    outStream.write(buff);
                    //write buff
                    downloaded += read;
                    publishProgress(downloaded, target);
                    if (isCancelled()) {
                        return null;
                    }
                }

                outStream.flush();

                return Uri.fromFile(new File(pathToApkFolder));
            } catch (IOException ignore) {
                ignore.printStackTrace();
                return null;
            } finally {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            }
        } else {
            return null;
        }
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }

Is there any default limitations in retrofit that I have to reconfigure to make this work.

Most helpful comment

You need to add @Streaming to the method, otherwise Retrofit will buffer the entire contents of the response in memory.

All 8 comments

You need to add @Streaming to the method, otherwise Retrofit will buffer the entire contents of the response in memory.

Wow!! Thanks for the fast response, I added Streaming annotation, But still it behaves the same, the issue exists the same.

outStream.write(buff);

should be

outputStream.write(buff, 0, read);

by the way.

If you are receiving an EOF exception then that is coming from the underlying HTTP client, not Retrofit itself. Usually this means that the content length didn't match the number of bytes sent across the wire.

Does it work if you just use HttpURLConnection to download the file?

Thanks again for the very fast response,
I tried this,

IOUtils.copy(inputStream, outStream); 

and it worked fine, And also your,

outputStream.write(buff, 0, read); 

which is what I needed to keep track of progress.

Thank you very much!!

@dioode where did you put IOUtils.copy(inputStream, outStream); I am having the same issue. :smile:

For who have same problem there is problems using Logger with @Streaming . get rid of logger will work. developer can write another API for methods will @Streaming and disable Logger for that.

Hi,

I used @Streaming and writeResponseBodyToDisk into AsyncTask and also as you suggested outputStream.write(fileReader, 0, read);
But still not able to write the full file into sd card(file download: 251636 of 7809748).

not works in 4.2.2

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Ne1c picture Ne1c  路  3Comments

JerzyPuchalski picture JerzyPuchalski  路  3Comments

vkislicins picture vkislicins  路  3Comments

chriskessel picture chriskessel  路  3Comments

colintheshots picture colintheshots  路  3Comments