Retrofit 2.0 单文件、多文件上传
来源:互联网 发布:手机怎么破解网络限制 编辑:程序博客网 时间:2024/06/05 10:26
最近项目空档期,学习了一下Retrofit 2.0文件上传,在网上查了好多资源,也踩了好多坑,还好经过努力,Retrofit2.0单文件、多文件上传的一个小demo弄出来了,记录下来方便以后自己查阅使用。
依赖:
compile 'com.android.support:appcompat-v7:24.2.0'compile 'com.squareup.retrofit2:retrofit:2.0.2'compile 'com.squareup.retrofit2:converter-gson:2.0.2'compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2'
使用Retrofit 2.0 上传文件,需要使用:Part & PartMap。
<span style="font-family:Microsoft YaHei;font-size:18px;">@Part,@PartMap:用于POST文件上传 其中@Part MultipartBody.Part代表文件,@Part(“key”) RequestBody代表参数 需要添加@Multipart表示支持文件上传的表单,Content-Type: multipart/form-data</span>
一、单文件上传:
@Multipart@POST("UploadServer")Call<BaseResponse<String>> upload(@Part("description") RequestBody description, @Part MultipartBody.Part file);
我们用这种方法提交单文件,下面是这个借口的使用方法:创建Api类获取FileUploadService:
public class Api { private static FileUploadService SERVICE; private static final String BASE_URL = "http://192.168.1.100:8080/UploadFileServer/"; public static FileUploadService getDefault() { if(SERVICE == null) { OkHttpClient client = new OkHttpClient.Builder().build(); SERVICE = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .client(client) .build().create(FileUploadService.class); } return SERVICE; }}
在activity里调用接口:private void uploadMonofile(String filename){ //先创建 service FileUploadService service = Api.getDefault(); //构建要上传的文件 File file = new File(filename); RequestBody requestFile = RequestBody.create(MediaType.parse("application/otcet-stream"), file); MultipartBody.Part body = MultipartBody.Part.createFormData("aFile", file.getName(), requestFile); String descriptionString = "This is a description"; RequestBody description = RequestBody.create( MediaType.parse("multipart/form-data"), descriptionString); Call<BaseResponse<String>> call = service.upload(description, body); call.enqueue(new Callback<BaseResponse<String>>() { @Override public void onResponse(Call<BaseResponse<String>> call, Response<BaseResponse<String>> response) { System.out.println("success"); Logger.e("success:" + response.body().getResultMessage()); } @Override public void onFailure(Call<BaseResponse<String>> call, Throwable t) { t.printStackTrace(); Logger.e("error:" + t.getMessage()); } });}
第二、多文件上传:
定义一个上传的网络请求Service:
/** * 通过 List<MultipartBody.Part> 传入多个part实现多文件上传 * @param parts 每个part代表一个 * @return 状态信息 */@Multipart@POST("UploadServer")Call<BaseResponse<String>> uploadFilesWithParts(@Part() List<MultipartBody.Part> parts);/** * 通过 MultipartBody和@body作为参数来实现多文件上传 * @param multipartBody MultipartBody包含多个Part * @return 状态信息 */@POST("UploadServer")Call<BaseResponse<String>> uploadFileWithRequestBody(@Body MultipartBody multipartBody);
由上可知,有两种方式实现上传
- 使用
@Multipart
注解方法,并用@Part
注解方法参数,类型是List<okhttp3.MultipartBody.Part>
- 不使用
@Multipart
注解方法,直接使用@Body
注解方法参数,类型是okhttp3.MultipartBody
可以看到,无论方法参数类型是MultipartBody.Part
还是MultipartBody
,这些类都不是Retrofit的类,而是okhttp实现上传的源生类。
MultipartBody
可以写一个方法,用于把
File
对象转化成MultipartBody
:public static MultipartBody filesToMultipartBody(List<File> files) { MultipartBody.Builder builder = new MultipartBody.Builder(); for (File file : files) { // TODO: 16-4-2 这里为了简单起见,没有判断file的类型 RequestBody requestBody = RequestBody.create(MediaType.parse("image/png"), file); builder.addFormDataPart("aFile", file.getName(), requestBody); } builder.setType(MultipartBody.FORM); MultipartBody multipartBody = builder.build(); return multipartBody;}
或者把File
转化成MultipartBody.Part
:public static List<MultipartBody.Part> filesToMultipartBodyParts(List<File> files) { List<MultipartBody.Part> parts = new ArrayList<>(files.size()); for (File file : files) { // TODO: 16-4-2 这里为了简单起见,没有判断file的类型 RequestBody requestBody = RequestBody.create(MediaType.parse("image/png"), file); MultipartBody.Part part = MultipartBody.Part.createFormData("aFile", file.getName(), requestBody); parts.add(part); } return parts;}
在Activity里调用接口private void uploadMultifile(ArrayList<File> mFileList) { MultipartBody body = MultipartBuilder.filesToMultipartBody(mFileList); Api.getDefault().uploadFileWithRequestBody(body) .enqueue(new Callback<BaseResponse<String>>() { @Override public void onResponse(Call<BaseResponse<String>> call, Response<BaseResponse<String>> response) { Logger.e("onResponse--" + response.body().getResultMessage()); if (response.isSuccessful()) { BaseResponse<String> body = response.body(); Logger.e("onResponse----success" ); } else { Log.d(TAG,"上传失败"); Logger.e("onResponse----fail" ); } } @Override public void onFailure(Call<BaseResponse<String>> call, Throwable t) { Logger.e("onResponse----onFailure"+ t.getMessage()); } });}
至此客户端核心代码基本完成,服务器核心代码:
需要用到两个重要的jar:commons-fileupload-1.2.1.jar commons-io-1.4.jar
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("有文件提交");
// 设置response的编码格式
response.setHeader("Content-type", "text/html;charset=UTF-8");
response.setCharacterEncoding("utf-8");
// 创建文件项目工厂对象
DiskFileItemFactory factory = new DiskFileItemFactory();
// 设置文件上传路径
// String upload = this.getServletContext().getRealPath("/");
String upload = "D:/aa/image/";
// 获取系统默认的临时文件保存路径,该路径为Tomcat根目录下的temp文件夹
String temp = System.getProperty("java.io.tmpdir");
// 设置缓冲区大小为 5M
factory.setSizeThreshold(1024 * 1024 * 5);
// 设置临时文件夹为temp
factory.setRepository(new File(temp));
// 用工厂实例化上传组件,ServletFileUpload 用来解析文件上传请求
ServletFileUpload servletFileUpload = new ServletFileUpload(factory);
// 解析结果放在List中
try {
List<FileItem> list = servletFileUpload.parseRequest(request);
for (FileItem item : list) {
String name = item.getFieldName();
InputStream is = item.getInputStream();
System.out.println("the current name is " + name);
if (name.contains("aFile")) {
try {
inputStream2File(is, upload + "\\" + /*
* System.
* currentTimeMillis
* () +
*/item.getName());
} catch (Exception e) {
e.printStackTrace();
}
} else {
String key = item.getName();
String value = item.getString();
System.out.println(key + "---" + value);
}
}
// out.write("success");
Gson gson = new Gson();
ResponseData data = new ResponseData<String>(200, "成功", "上传了文件");
String gsonStr = gson.toJson(data);
System.out.println("响应数据::" + gsonStr);
response.getWriter().print(gsonStr);
} catch (FileUploadException e) {
e.printStackTrace();
System.out.println("failure");
}
PrintWriter out = response.getWriter();
out.flush();
out.close();
}
// 流转化成字符串
public static String inputStream2String(InputStream is) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int i = -1;
while ((i = is.read()) != -1) {
baos.write(i);
}
return baos.toString();
}
// 流转化成文件
public static void inputStream2File(InputStream is, String savePath)
throws Exception {
System.out.println("the file path is :" + savePath);
File file = new File(savePath);
InputStream inputSteam = is;
BufferedInputStream fis = new BufferedInputStream(inputSteam);
FileOutputStream fos = new FileOutputStream(file);
int f;
while ((f = fis.read()) != -1) {
fos.write(f);
}
fos.flush();
fos.close();
fis.close();
inputSteam.close();
}
至此一个Retrofit 2.0 上传单文件、多文件的小demo就完成了
注意:Retrofit 2.0 依赖不要使用:'com.squareup.retrofit2:retrofit:2.0.0-beta4' beta版,说多了都是泪啊。
参考:
http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=1117
http://www.chenkaihua.com/2016/04/02/retrofit2-upload-multipart-files.html
还有参考其他的,不过忘记了。sorry!
源码下载
- Retrofit 2.0 单文件、多文件上传
- Retrofit 2.0文件上传
- Retrofit 2.0 文件上传类型
- 使用Retrofit上传文件
- Retrofit上传文件
- Retrofit 上传文件
- retrofit 上传文件
- Retrofit上传文件
- retrofit+rxjava 上传文件
- Retrofit上传文件
- Retrofit 上传文件
- 一个基于Retrofit的单文件上传、下载框架
- 单/多文件上传
- 单多文件上传
- Retrofit 2.0 轻松实现多文件/图片上传
- Retrofit 2.0 文件上传类型错误
- Retrofit 上传多张图片/文件
- Retrofit之表单提交、多文件上传
- node.js 包的概念
- HTML DOM基本概念及Element.getAttribute("value") 与Attribute.value差异
- Android 视图架构学习笔记
- 大神之路:重学Android——Android多媒体MediaPlayer
- 51Nod-1335-子序列翻转
- Retrofit 2.0 单文件、多文件上传
- 深入探讨Iterator模式
- 事件分发学习笔记
- actionbaractivity 与 appcompatactivity
- TJI读书笔记10-复用类
- w3cschool之JavaScript学习
- listView convertView缓存机制 & 异步加载图片 问题剖析
- Lambda 表达式
- 归并排序算法