使用Retrofit2 RxJava 文件上传

时间:2022-04-10 17:50:51

前言

Retrofit2 的文件上传在官方网站上并没有多说,只是说可以使用@Multipart注解即可使用,但是没有细致的去讲解这块怎么用。
在github的issus上有几篇文章,讲的有点乱,现在整理一下,如何使用Retrofit2 和 RxJava 来实现文件上传。

单文件上传

Server配置

    @POST("/file")
@Multipart
Observable<DataResponse<UploadFile>> uploadFile(@Part("file\"; filename=\"avatar.png\"") RequestBody file);

此处@Part(“file\”; filename=\”avatar.png\”“)注释的含义是该RequestBody 的名称为file,上传的文件名称为avatar.png。
@Path注解中的filename与上传文件的真实名称可以不匹配

RxJava调用

rxjava

public void uploadFiles(File file){
//代理模式生成对应server的实例化对象
FileUploadServer server = getRetrofit().create(FileUploadServer.class);
//创建RequwstBody对象
RequestBody requestBody = RequestBody.create(MediaType.parse("image/*"), file);
//使用RxJava方式调度任务并监听
server.uploadFile(requestBody)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.map(new ResponseFunc<UploadFile>())
.subscribe(new Subscriber<UploadFile>() {
@Override
public void onCompleted() {

}

@Override
public void onError(Throwable e) {
DebugLog.wtf("upload error" + e.getMessage());
}

@Override
public void onNext(UploadFile uploadFile) {
DebugLog.wtf("upload Success" + uploadFile.uploadFileName());
}
});
}

多文件上传

Server配置

@Multipart
@POST("/files")
Call<UploadInformationTransfer> uploadFiles(@PartMap Map<String, RequestBody> params)
;

此处使用@PartMap注释,传递多个Part,以实现多文件上传。

RxJava调用

rxjava

public void uploadFiles(File... files){
//代理模式生成对应server的实例化对象
FileUploadServer server = getRetrofit().create(FileUploadServer.class);
//组装partMap对象
Map<String, RequestBody> partMap = new HashMap<>();
for(File file : files ){
RequestBody fileBody = RequestBody.create(MediaType.parse("image/*"), file);
partMap.put("file\"; filename=\""+file.getName()+"\"", fileBody);
}
//使用RxJava方式调度任务并监听
server.uploadFiles(partMap)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.map(new ResponseFunc<UploadFile>())
.subscribe(new Subscriber<UploadFile>() {
@Override
public void onCompleted() {

}

@Override
public void onError(Throwable e) {
DebugLog.wtf("upload error" + e.getMessage());
}

@Override
public void onNext(UploadFile uploadFile) {
DebugLog.wtf("upload Success" + uploadFile.uploadFileName());
}
});
}

关键还是在于partMap.put(“file\”; filename=\”“+file.getName()+”\”“, fileBody);此处的key就充当了单文件上传时@Part中设置的参数。

混合上传

现实使用中,一般会有一种需求是,传文件的同时需要上传一些其他的字段,这怎么办?

改造自单文件上传的代码

Server

    @POST("/file")
@Multipart
Observable<DataResponse<UploadFile>> uploadFile(@Part("file\"; filename=\"avatar.png\"") RequestBody file,@Part("nickName") RequestBody nickName);

RxJava调用

rxjava

public void uploadFiles(File file,String nickName){
//代理模式生成对应server的实例化对象
FileUploadServer server = getRetrofit().create(FileUploadServer.class);
//创建RequwstBody对象
RequestBody requestBody = RequestBody.create(MediaType.parse("image/*"), file);
//创建nickNameBody对象
RequestBody nickNameBody = RequestBody.create(MediaType.parse("text/plain"), nickName);
//使用RxJava方式调度任务并监听
server.uploadFile(requestBody,nickNameBody)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.map(new ResponseFunc<UploadFile>())
.subscribe(new Subscriber<UploadFile>() {
@Override
public void onCompleted() {

}

@Override
public void onError(Throwable e) {
DebugLog.wtf("upload error" + e.getMessage());
}

@Override
public void onNext(UploadFile uploadFile) {
DebugLog.wtf("upload Success" + uploadFile.uploadFileName());
}
});
}

其实就是增加了一个@Part,只不过该Part是一个text/plain多媒体类型的。

改造自多文件上传的代码

Server配置不变

RxJava调用

rxjava

public void uploadFiles(File... files){
//代理模式生成对应server的实例化对象
FileUploadServer server = getRetrofit().create(FileUploadServer.class);
//组装partMap对象
Map<String, RequestBody> partMap = new HashMap<>();
for(File file : files ){
RequestBody fileBody = RequestBody.create(MediaType.parse("image/*"), file);
partMap.put("file\"; filename=\""+file.getName()+"\"", fileBody);
}
RequestBody nickNameBody = RequestBody.create(MediaType.parse("text/plain"), nickName);
partMap.put("nickName" , nickNameBody);
//使用RxJava方式调度任务并监听
server.uploadFiles(partMap)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.map(new ResponseFunc<UploadFile>())
.subscribe(new Subscriber<UploadFile>() {
@Override
public void onCompleted() {

}

@Override
public void onError(Throwable e) {
DebugLog.wtf("upload error" + e.getMessage());
}

@Override
public void onNext(UploadFile uploadFile) {
DebugLog.wtf("upload Success" + uploadFile.uploadFileName());
}
});
}

其实只是在partMap中put了一个RequestBody。
partMap.put(“nickName” , nickNameBody);

UploadFile.java

public class UploadFile {
private String fid;
private String sourceFileName;
private String uploadFileName;

public String getFid() {
return fid;
}

public void setFid(String fid) {
this.fid = fid;
}

public String getSourceFileName() {
return fileName;
}

public void setSourceFileName(String sourceFileName) {
this.sourceFileName = sourceFileName;
}

public String getUploadFileName() {
return uploadFileName;
}

public void setUploadFileName(String uploadFileName) {
this.uploadFileName = uploadFileName;
}
}