Retrofit之文件下载

作者: ChicoChen | 来源:发表于2017-01-08 22:40 被阅读513次

    请求声明

    // option 1: a resource relative to your base URL
    @GET("/resource/example.zip")
    Call<ResponseBody> downloadFileWithFixedUrl();
    // option 2: using a dynamic URL
    @GET
    Call<ResponseBody> downloadFileWithDynamicUrlSync(@Url String fileUrl); 
    

    如果要下载的文件是静态资源(始终位于服务器上的同一位置),并且基本URL所引用的服务器上,您可以使用选项1,它看起来像一个常规的Retrofit 2请求声明.
    下载文件我们是使用ResponseBody作为返回类型,这里最好不要改成其他的类型
    option2中可以轻松地将动态值作为完整网址传递到请求调用。

    请求调用

    FileDownloadService downloadService = RetrofitClient.create(FileDownloadService.class);
    Call<ResponseBody> call = downloadService.downloadFileWithDynamicUrlSync(fileUrl);
    call.enqueue(new Callback<ResponseBody>() {  
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            if (response.isSuccess()) {
                boolean writtenToDisk = writeResponseBodyToDisk(response.body());
                Log.d(TAG, "下载成功");
            } else {
                Log.d(TAG, "下载失败");
            }
        }
        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
            Log.e(TAG, "error");
        }
    });
    

    FileDownloadService类是你实现的请求声明,就是上面介绍的。
    RetrofitClient代码如下:

    public class JuheRetrofit extends BaseRetrofit{
    
        private static OkHttpClient httpClient;
        private static Gson gson;
        private static HttpLoggingInterceptor logging;
        private static Retrofit retrofit;
    
        /**
         * 获取接口ApiService
         *
         * @return
         */
        public static JuheApiService getJuheApiService() {
            return getRetrofit().create(JuheApiService.class);
        }
    
        /**
         * 指定Gons格式
         *
         * @return
         */
        protected static Gson getGson() {
            if (gson == null) {
                gson = new GsonBuilder()
                        .setLenient()
                        .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
                        .create();
            }
            return gson;
        }
    
        /**
         * 设置HttpClient设置
         *
         * @return
         */
        protected static OkHttpClient getOkHttpClient() {
            if (httpClient == null) {
                OkHttpClient.Builder builder = new OkHttpClient.Builder();
                if (BuildConfig.DEBUG) {
                    builder.addInterceptor(getHttpLoggingInterceptor());
                }
                builder.connectTimeout(20, TimeUnit.SECONDS);
                httpClient = builder.build();
            }
            return httpClient;
        }
    
    
        /**
         * Log信息拦截器
         *
         * @return
         */
        protected static Interceptor getHttpLoggingInterceptor() {
            if (logging == null) {
                logging = new HttpLoggingInterceptor();
                logging.setLevel(HttpLoggingInterceptor.Level.BODY);
            }
            return logging;
        }
    
        /**
         * 获取Retrofit
         *
         * @return
         */
        private static Retrofit getRetrofit() {
            if (retrofit == null) {
                retrofit = new Retrofit.Builder()
                        .baseUrl(UrlConstant.BASE_JUHE)
                        .client(getOkHttpClient())
                        .addConverterFactory(GsonConverterFactory.create(getGson()))
                        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                        .build();
            }
            return retrofit;
        }
    }
    

    定义了声明文件,也是现实请求调用,最后就要处理ResponseBody数据了,上面我们通过writeFileToSDCard()方法将文件保存到手机SDCard中

    数据保存

    private boolean writeFileToSDCard(ResponseBody body) {  
        try {
            // todo change the file location/name according to your needs
            File futureStudioIconFile = new File(getExternalFilesDir(null) + File.separator + "Future Studio Icon.png");
            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;
                    Log.d(TAG, "file download: " + fileSizeDownloaded + " of " + fileSize);
                }
                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;
        }
    }
    

    有一个问题:在默认情况下,Retrofit在处理结果之前将整个服务器响应放入内存,这适用于一些JSON或XML响应,但大文件可以轻松导致内存不足错误
    所以如果你下载的是大文件,你需要使用@Streaming注解,如下:

    @Streaming
    @GET
    Call<ResponseBody> downloadFileWithDynamicUrlAsync(@Url String fileUrl); 
    

    注意,如果你使用了@Streaming,不要忘了把上面的writeFileToSDCard()方法放在异步线程中,否则可能会抛出android.os.NetworkOnMainThreadException异常。

    以上就是Retrofig文件下载的所有内容了,如果不清楚了可以互相交流

    相关文章

      网友评论

        本文标题:Retrofit之文件下载

        本文链接:https://www.haomeiwen.com/subject/telcbttx.html