请求声明
// 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异常。
以上就是Retrofit文件下载的所有内容了,如果不清楚了可以互相交流