基本用法
文件1:请求返回的实体类
public class UploadBean {
private String imageUrl;
private String textFile;
public String getImageUrl() { return imageUrl; }
public void setImageUrl(String imageUrl) { this.imageUrl = imageUrl; }
public String getTextFile() { return textFile; }
public void setTextFile(String textFile) { this.textFile = textFile; }
}
文件2:定义请求接口
public interface UploadService {
// [途径A]文件上传使用MultipartBody.Part对象
@Multipart
@POST("/file/image")
Call<UploadBean> uploadDouble(@Part MultipartBody.Part file1,
@Part MultipartBody.Part file2,
@Part("username") RequestBody username,
@Part("password") RequestBody password);
}
文件3:具体调用的地方
/**
* 上传文件
*
* @param filePathName1 文件1路径及文件名
* @param filePathName2 文件2路径及文件名
*/
public void uploadFile(String filePathName1, String filePathName2) {
// 生成Retrofit
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://192.168.1.6:8080/upload/")
.addConverterFactory(GsonConverterFactory.create())
.build();
// 生成Service
UploadService uploadService = retrofit.create(UploadService.class);
// 要上传的文件
File file1 = new File(filePathName1);
File file2 = new File(filePathName2);
// 创建 RequestBody,用于封装构建MultipartBody.Part。设置MediaType:application/octet-stream(一说:multipart/form-data,待检验)
RequestBody requestBody1 = RequestBody.create(MediaType.parse("application/octet-stream"), file1);
RequestBody requestBody2 = RequestBody.create(MediaType.parse("application/octet-stream"), file2);
// MultipartBody.Part 和后端约定好Key,这里的partName暂时用"file_key_*"
MultipartBody.Part partFile1 = MultipartBody.Part.createFormData("file_key_1", file1.getName(), requestBody1);
MultipartBody.Part partFile2 = MultipartBody.Part.createFormData("file_key_2", file2.getName(), requestBody2);
// 添加参数用户名和密码,并且是文本类型,设置MediaType为文本类型(一说:multipart/form-data,待检验)
RequestBody userName = RequestBody.create(MediaType.parse("text/plain"), "username");
RequestBody password = RequestBody.create(MediaType.parse("text/plain"), "password");
// 执行请求
Call<UploadBean> call = uploadService.uploadDouble(partFile1, partFile2, userName, password);
call.enqueue(new Callback<UploadBean>() {
@Override
public void onResponse(Call<UploadBean> call, Response<UploadBean> response) {
Log.e("TAG", response.body().getImageUrl());
}
@Override
public void onFailure(Call<UploadBean> call, Throwable t) {
t.printStackTrace();
}
});
}
解析
上述基本用法使用的是上传有限确定个文件,此种方式还可以简化,另外还可以上传任意个文件,一并总结如下:
MultipartBody.Part参数
) // [方式A]优先确定个文件上传使用MultipartBody.Part对象
@Multipart
@POST("/file/image")
Call<UploadBean> uploadDouble(@Part MultipartBody.Part file1,
@Part MultipartBody.Part file2,
@Part("username") RequestBody username,
@Part("password") RequestBody password);
注意:此处 @Part 如果使用 MultipartBody.Part 作为参数类型,@Part 不能携带参数,空参数如上述格式。
如果携带参数,写成:@Part("image") MultipartBody.Part file1
则报错:@Part parameters using the MultipartBody.Part must not include a part name in the annotation
调用处使用 MultipartBody.Part
来构造一个Part对象参数
// 要上传的文件
String filePathName1 = Environment.getExternalStorageDirectory() + File.separator + "sample_01.jpg";
String filePathName2 = Environment.getExternalStorageDirectory() + File.separator + "sample_02.jpg";
File file1 = new File(filePathName1);
File file2 = new File(filePathName2);
// 创建 RequestBody,用于封装构建MultipartBody.Part。设置MediaType为:multipart/form-data
RequestBody requestBody1 = RequestBody.create(MediaType.parse("multipart/form-data"), file1);
RequestBody requestBody2 = RequestBody.create(MediaType.parse("multipart/form-data"), file2);
// MultipartBody.Part 和后端约定好Key,这里的partName暂时用"file_key_*"
MultipartBody.Part partFile1 = MultipartBody.Part.createFormData("file_key_1", file1.getName(), requestBody1);
MultipartBody.Part partFile2 = MultipartBody.Part.createFormData("file_key_2", file2.getName(), requestBody2);
// 添加参数用户名和密码,并且是文本类型,设置MediaType为:multipart/form-data
RequestBody userName = RequestBody.create(MediaType.parse("multipart/form-data"), "username");
RequestBody password = RequestBody.create(MediaType.parse("multipart/form-data"), "password");
// 执行请求
Call<UploadBean> call = uploadService.uploadDouble(partFile1, partFile2, userName, password);
RequestBody
) // [方式B]文件上传使用RequestBody对象
@Multipart
@POST("/file/image")
Call<UploadBean> uploadDouble(@Part("pic01\"; filename=\"sample_01.png") RequestBody file1,
@Part("pic02\"; filename=\"sample_01.png") RequestBody file2,
@Part("username") RequestBody username,
@Part("password") RequestBody password);
注意:此处 @Part 如果使用 RequestBody 作为参数类型,@Part 其必须携带参数,参数如上述格式。
如果未携带参数,写成:@Part RequestBody file1
则报错:@Part annotation must supply a name or use MultipartBody.Part parameter type. (parameter #1)
注意:如果此处 @Part 如果使用 RequestBody 作为参数类型,@Part 携带的参数不如上述格式,目的为了上传文件。
如果携带参数,写成:@Part("image") RequestBody file1
则服务端识别不出来这是一个文件,会当做一个参数上传的例子,所以参数格式要正确
调用处使用直接使用 RequestBody
来构造一个RequestBody对象参数
// 添加要上传的文件,设置MediaType为:multipart/form-data
RequestBody requestBody1 = RequestBody.create(MediaType.parse("multipart/form-data"), file1);
RequestBody requestBody2 = RequestBody.create(MediaType.parse("multipart/form-data"), file2);
// 添加其他参数,设置MediaType为:multipart/form-data
RequestBody userName = RequestBody.create(MediaType.parse("multipart/form-data"), "username");
RequestBody password = RequestBody.create(MediaType.parse("multipart/form-data"), "password");
// 执行请求
Call<UploadBean> call = uploadService.uploadDouble(requestBody1, requestBody2, userName, password);
@Part
实现)接口
// [方式C]文件上传使用@Part + List<MultipartBody.Part>对象的方式
@Multipart
@POST("/file/image")
Call<UploadAurora> uploadMulti(@Part List<MultipartBody.Part> parts,
@Part("username") RequestBody username,
@Part("password") RequestBody password);
调用
// 要上传的文件
String filePathName1 = Environment.getExternalStorageDirectory() + File.separator + "sample_01.jpg";
String filePathName2 = Environment.getExternalStorageDirectory() + File.separator + "sample_02.jpg";
File file1 = new File(filePathName1);
File file2 = new File(filePathName2);
// 添加要上传的文件,设置MediaType为:multipart/form-data
RequestBody requestBody1 = RequestBody.create(MediaType.parse("multipart/form-data"), file1);
RequestBody requestBody2 = RequestBody.create(MediaType.parse("multipart/form-data"), file2);
// MultipartBody.Part 和后端约定好Key,这里的partName暂时用"file_key_*"
MultipartBody.Part partFile1 = MultipartBody.Part.createFormData("file_key_1", file1.getName(), requestBody1);
MultipartBody.Part partFile2 = MultipartBody.Part.createFormData("file_key_2", file2.getName(), requestBody2);
// 添加其他参数,设置MediaType为:multipart/form-data
RequestBody userName = RequestBody.create(MediaType.parse("multipart/form-data"), "username");
RequestBody password = RequestBody.create(MediaType.parse("multipart/form-data"), "password");
// 添加任意MultipartBody.Part对象进List,集中处理
List<MultipartBody.Part> partList = new ArrayList<>();
partList.add(partFile1);
partList.add(partFile2);
// 执行请求
Call<UploadAurora> call = uploadService.uploadMulti(partList, userName, password);
@PartMap
实现)接口
// [方式C]文件上传使用@PartMap + RequestBody对象的方式
@Multipart
@POST("/file/image")
Call<UploadAurora> uploadMulti(@PartMap Map<String, RequestBody> requestBodyMap,
@Part("username") RequestBody username,
@Part("password") RequestBody password);
调用
// 要上传的文件
String filePathName1 = Environment.getExternalStorageDirectory() + File.separator + "sample_01.jpg";
String filePathName2 = Environment.getExternalStorageDirectory() + File.separator + "sample_02.jpg";
File file1 = new File(filePathName1);
File file2 = new File(filePathName2);
// 添加要上传的文件,设置MediaType为:multipart/form-data
RequestBody requestBody1 = RequestBody.create(MediaType.parse("multipart/form-data"), file1);
RequestBody requestBody2 = RequestBody.create(MediaType.parse("multipart/form-data"), file2);
// 添加其他参数,设置MediaType为:multipart/form-data
RequestBody userName = RequestBody.create(MediaType.parse("multipart/form-data"), "username");
RequestBody password = RequestBody.create(MediaType.parse("multipart/form-data"), "password");
// 添加任意RequestBody对象进Map,集中处理
Map<String, RequestBody> requestBodyMap = new HashMap<>();
requestBodyMap.put("image\"; filename=\"" + file1.getName(), requestBody1); //这里的key必须这么写,否则服务端无法识别
requestBodyMap.put("image\"; filename=\"" + "sample_02.jpg", requestBody2); //这里的key必须这么写,否则服务端无法识别
// 执行请求
Call<UploadAurora> call = uploadService.uploadMulti(requestBodyMap, userName, password);
参考:https://www.jianshu.com/p/74b7da380855 | Retrofit学习之文件和参数上传
参考:https://www.cnblogs.com/zhujiabin/p/7601658.html | Android Retrofit 2.0文件上传
参考:https://blog.csdn.net/jdsjlzx/article/details/52246114 | Android Retrofit 实现(图文上传)文字(参数)和多张图片一起上传
参考:https://www.jianshu.com/p/acfefb0a204f | Retrofit 2.0 超能实践(三),轻松实现多文件/图片上传/Json字符串/表单
参考:https://blog.csdn.net/sk719887916/article/details/51755427 | Retrofit 2.0 超能实践(三),轻松实现文件/多图片上传/Json..
参考:https://blog.csdn.net/qq_32090185/article/details/86573530 | Android上传单文件和多文件(后台使用MultipartFile)