Retrofit2 的文件上传在官方网站上并没有多说,只是说可以使用@Multipart注解即可使用,但是没有细致的去讲解这块怎么用。
在github的issus上有几篇文章,讲的有点乱,现在整理一下,如何使用Retrofit2 和 RxJava 来实现文件上传。
@POST("/file")
@Multipart
Observable> uploadFile(@Part("file\"; filename=\"avatar.png\"") RequestBody file);
此处@Part(“file\”; filename=\”avatar.png\”“)注释的含义是该RequestBody 的名称为file,上传的文件名称为avatar.png。
@Path注解中的filename与上传文件的真实名称可以不匹配。
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())
.subscribe(new Subscriber() {
@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());
}
});
}
@Multipart
@POST("/files")
Call uploadFiles(@PartMap Map params) ;
此处使用@PartMap注释,传递多个Part,以实现多文件上传。
rxjava
public void uploadFiles(File... files){
//代理模式生成对应server的实例化对象
FileUploadServer server = getRetrofit().create(FileUploadServer.class);
//组装partMap对象
Map 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())
.subscribe(new Subscriber() {
@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中设置的参数。
现实使用中,一般会有一种需求是,传文件的同时需要上传一些其他的字段,这怎么办?
@POST("/file")
@Multipart
Observable> uploadFile(@Part("file\"; filename=\"avatar.png\"") RequestBody file,@Part("nickName") RequestBody nickName);
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())
.subscribe(new Subscriber() {
@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多媒体类型的。
rxjava
public void uploadFiles(File... files){
//代理模式生成对应server的实例化对象
FileUploadServer server = getRetrofit().create(FileUploadServer.class);
//组装partMap对象
Map 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())
.subscribe(new Subscriber() {
@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);
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;
}
}