Retrofit2文件上傳與下載通俗易懂教程赂苗。
之前在使用retrofit的時(shí)候,遇到文件上傳和下載的功能,搜索了好久才完成功能,搜索的有很多都讓人困惑,更有些寫的讓人絕望,我就想著自己寫一篇簡(jiǎn)單易懂的,如對(duì)您有幫助,可以點(diǎn)個(gè)贊和喜歡,一個(gè)小小的舉動(dòng)就是對(duì)作者最大的鼓勵(lì)蕉鸳。Thanks?(?ω?)?
源碼地址
https://github.com/QiaoYang0923/RetrofitDownloadAndUpLoading
文件上傳:(包括多文件上傳)
第一步:創(chuàng)建服務(wù)返回?cái)?shù)據(jù)的bean類;(此處服務(wù)器返回的是json字符串);
public class BaseBean{
private int Code;
private String Msg;
private String Data;
//...setget方法
}
第二步:創(chuàng)建用于描述網(wǎng)絡(luò)請(qǐng)求的接口
public interface Api {
/**
* 上傳
* Multipart 這個(gè)注解代表多表單上傳
* @param partList 表單信息
* @return .
*/
@Multipart
@POST("服務(wù)器地址(就創(chuàng)建retrofit設(shè)置的基站地址后面的具體地址)")
Call<BaseBean> upLoading(@Part List<MultipartBody.Part> partList);
}
第三步:創(chuàng)建表單,里面存儲(chǔ)服務(wù)器本接口所需要的數(shù)據(jù);
參數(shù)添加
MultipartBody.Builder builder = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
//在這里添加服務(wù)器除了文件之外的其他參數(shù)
.addFormDataPart("參數(shù)1", "值1")
.addFormDataPart("參數(shù)2", "值2");
創(chuàng)建文件(你需要上傳到服務(wù)器的文件)
File file = new File(file1Location); //file1Location文件的路徑 ,我是在手機(jī)存儲(chǔ)根目錄下創(chuàng)建了一個(gè)文件夾,里面放著了一張圖片;
設(shè)置文件的格式
RequestBody imageBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
//添加文件(uploadfile就是你服務(wù)器中需要的文件參數(shù))
builder.addFormDataPart("uploadfile", file.getName(), imageBody);
生成接口需要的list
List<MultipartBody.Part> parts = builder.build().parts();
創(chuàng)建設(shè)置OkHttpClient
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(20, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS)
//允許失敗重試
.retryOnConnectionFailure(true)
.build();
創(chuàng)建retrofit實(shí)例對(duì)象
Retrofit retrofit = new Retrofit.Builder()
//設(shè)置基站地址(基站地址+描述網(wǎng)絡(luò)請(qǐng)求的接口上面注釋的Post地址,就是要上傳文件到服務(wù)器的地址,
// 這只是一種設(shè)置地址的方法,還有其他方式,不在贅述)
.baseUrl("你的基站地址")
//設(shè)置委托,使用OKHttp聯(lián)網(wǎng),也可以設(shè)置其他的;
.client(okHttpClient)
//設(shè)置數(shù)據(jù)解析器,如果沒(méi)有這個(gè)類需要添加依賴:
.addConverterFactory(GsonConverterFactory.create())
//設(shè)置支持rxJava
// .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
實(shí)例化請(qǐng)求接口,把表單傳遞過(guò)去;
Call<BaseBean> call = retrofit.create(Api.class).upLoading(parts);
//開(kāi)始請(qǐng)求
call.enqueue(new Callback<BaseBean>() {
@Override
public void onResponse(Call<BaseBean> call, Response<BaseBean> response) {
//聯(lián)網(wǎng)有響應(yīng)或有返回?cái)?shù)據(jù)
System.out.println(response.body().toString());
}
@Override
public void onFailure(Call<BaseBean> call, Throwable t) {
//連接失敗,多數(shù)是網(wǎng)絡(luò)不可用導(dǎo)致的
System.out.println("網(wǎng)絡(luò)不可用");
}
});
}
這就ok了,單個(gè)文件上傳完畢!!!
多文件上傳(以兩個(gè)文件為例)
對(duì)比一個(gè)文件,這個(gè)只需要在[設(shè)置文件的格式] 這一步,多添加一個(gè)即可;
RequestBody imageBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
RequestBody imageBody1 = RequestBody.create(MediaType.parse("multipart/form-data"), file1);
//添加文件(uploadfile就是你服務(wù)器中需要的文件參數(shù))
builder.addFormDataPart("uploadfile", file.getName(), imageBody);
builder.addFormDataPart("uploadfile1", file1.getName(), imageBody1);
接下來(lái)看文件下載?
文件下載:
首先還是要在API接口創(chuàng)建一個(gè)方法;
/**
* 下載文件
* 如果下載大文件的一定要加上 @Streaming 注解
*
* @param fileUrl 文件的路徑
* @return 請(qǐng)求call
*/
@GET
Call<ResponseBody> download(@Url String fileUrl);
然后就是創(chuàng)建一個(gè)retrofit對(duì)象,跟上面一樣(由于每次創(chuàng)建retrofit對(duì)象會(huì)用到很多重復(fù)的代碼,可以抽取成一個(gè)公共方法)
實(shí)例化請(qǐng)求接口:
我在百度上找到一張圖片,把他的地址拆分了一下,最后一個(gè)斜杠之前的url設(shè)置為了baseUrl,斜杠之后設(shè)置在這里;
地址拆分: .baseUrl("https://gss3.bdstatic.com/-Po3dSag_xI4khGkpoWK1HF6hhy/baike/w%3D268%3Bg%3D0/sign=e3dc64d05a3d26972ed30f5b6dc0d5c6/")
//整體地址https://gss3.bdstatic.com/Po3dSag_xI4khGkpoWK1HF6hhy/baike/w%3D268%3Bg%3D0/sign=e3dc64d05a3d26972ed30f5b6dc0d5c6/(在這里拆分了)241f95cad1c8a7868a2713146c09c93d70cf509e.jpg
Call<ResponseBody> download = retrofit.create(Api.class).download("241f95cad1c8a7868a2713146c09c93d70cf509e.jpg");
download.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response != null && response.isSuccessful()) {
// writeResponseBodyToDisk 是我寫的下載保存本地工具類,可以參考一下
boolean toDisk = writeResponseBodyToDisk(response.body());
if (toDisk) {
System.out.println("下載成功請(qǐng)查看");
} else {
System.out.println("下載失敗,請(qǐng)稍后重試");
}
} else {
System.out.println("服務(wù)器返回錯(cuò)誤");
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
//連接失敗,多數(shù)是網(wǎng)絡(luò)不可用導(dǎo)致的
System.out.println("網(wǎng)絡(luò)不可用");
}
});
writeResponseBodyToDisk(下載文件保存到本地工具類)
/**
* 下載到本地
*
* @param body 內(nèi)容
* @return 成功或者失敗
*/
private boolean writeResponseBodyToDisk(ResponseBody body) {
try {
//判斷文件夾是否存在
File files = new File(SD_HOME_DIR);//跟目錄一個(gè)文件夾
if (!files.exists()) {
//不存在就創(chuàng)建出來(lái)
files.mkdirs();
}
//創(chuàng)建一個(gè)文件
File futureStudioIconFile = new File(SD_HOME_DIR + "download.jpg");
//初始化輸入流
InputStream inputStream = null;
//初始化輸出流
OutputStream outputStream = null;
try {
//設(shè)置每次讀寫的字節(jié)
byte[] fileReader = new byte[4096];
long fileSize = body.contentLength();
long fileSizeDownloaded = 0;
//請(qǐng)求返回的字節(jié)流
inputStream = body.byteStream();
//創(chuàng)建輸出流
outputStream = new FileOutputStream(futureStudioIconFile);
//進(jìn)行讀取操作
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
break;
}
//進(jìn)行寫入操作
outputStream.write(fileReader, 0, read);
fileSizeDownloaded += read;
}
//刷新
outputStream.flush();
return true;
} catch (IOException e) {
return false;
} finally {
if (inputStream != null) {
//關(guān)閉輸入流
inputStream.close();
}
if (outputStream != null) {
//關(guān)閉輸出流
outputStream.close();
}
}
} catch (IOException e) {
return false;
}
}
下載下來(lái)的圖片展示
241f95cad1c8a7868a2713146c09c93d70cf509e.jpg