通过前两篇姿势的入门
- [Retrofit 2.0
超能实践,完美支持Https传输]//tamicer.github.io/2017/03/15/jiamichuanshu_okhttp/) - [Retrofit2.0
完美同步Cookie实现免登录]https://tamicer.github.io/2017/03/14/12/)
本文出自:http://tamicer.com Tamic
通过对Retrofit2.0的前两篇的基础入门和案例实践,掌握了怎么样使用Retrofit访问网络,加入自定义header头,包括加入SSL证书,基本的调试基础,cookie同步问题,但很多场景需求是需要文件的上传的,今天主题就来分享怎么用Retrofit2.0 上传文件和图片,表单,包括上传Json等。
使用 Retrofit1.x上传文件
大家都知道在2.0以前版本上传图片的姿势
public interface ApiManager {
@Multipart
@POST("/user/addCarInfo")
void addCarInfo(@QueryMap Map<String, Object> options, @Part("file") TypedFile file, Callback<JsonElement> response);
}
使用 Retrofit 2.X 上传
Retrofit 2.X上传文件
使用2.0,我们发现以前的TypedFile类型被私有化了 ,无法继续使用1.9的传方式,因此2.x提供了上传方案,可以MultipartBody.Part代替。
public interface FileUploadService {
@Multipart
@POST("upload")
Call<ResponseBody> upload(@Part("description") RequestBody description,
@Part MultipartBody.Part file);
}
具体用法。
先看一个基本的用法:
// 创建 RequestBody,用于封装构建RequestBody
RequestBody requestFile =
RequestBody.create(MediaType.parse("multipart/form-data"), file);
// MultipartBody.Part 和后端约定好Key,这里的partName是用image
MultipartBody.Part body =
MultipartBody.Part.createFormData("image", file.getName(), requestFile);
// 添加描述
String descriptionString = "hello, 这是文件描述";
RequestBody description =
RequestBody.create(
MediaType.parse("multipart/form-data"), descriptionString);
// 执行请求
Call<ResponseBody> call = service.upload(description, body);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call,
Response<ResponseBody> response) {
Log.v("Upload", "success");
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.e("Upload error:", t.getMessage());
}
});
}
上报一张图片
@Multipart
@POST("you methd url upload/")
Call<ResponseBody> uploadFile(
@Part("avatar\\\\\\\\\\\\\\\\"; filename=\\\\\\\\\\\\\\\\"avatar.jpg") RequestBody file);
上报数量确定的多张图片
@POST("upload/")
Call<ResponseBody> uploadFiles(@Part("filename") String description,
@Part("pic\\\\\\\\\\\\\\\\"; filename=\\\\\\\\\\\\\\\\"image1.png") RequestBody imgs1,
@Part("pic\\\\\\\\\\\\\\\\"; filename=\\\\\\\\\\\\\\\\"image2.png") RequestBody imgs2,
@Part("pic\\\\\\\\\\\\\\\\"; filename=\\\\\\\\\\\\\\\\"image3.png") RequestBody imgs3,
@Part("pic\\\\\\\\\\\\\\\\"; filename=\\\\\\\\\\\\\\\\"image4.png") RequestBody imgs4);
##如果图片数量不确定 ##
@Multipart
@POST()
Observable<ResponseBody> uploadFiles(
@Url String url,
@Part("filename") String description,
@PartMap() Map<String, RequestBody> maps);
或者:
@Multipart
@POST()
Observable<ResponseBody> uploads(
@Url String url,
@Part("description") RequestBody description,
@Part("filekey") MultipartBody.Part file);
图文同时上报
Part方式
|
|
扩展一下:
|
|
java代码:
|
|
更简单的用Body方式:
|
|
Java代码:
|
|
此种方式让你很好的解决了用户注册问题,包含用户全部信息和头像,完美解决你想用表单一起将文字和图片一起提交的情况!
表单提交
很多时候想用表单的方式:
|
|
Java代码:
|
|
##Json提交
上传Json
|
|
upLoadJson
也可以具体指明Content-Type
为 “application/json
”格式的
具体组装我们的RequestBody则可以这样:
|
|
接着可以这样调用:
|
|
至于服务器返回什么类型的model, 开发者可以自定义, 譬如你可以把APi 中的 ResponseBody
指定为你自己的javaBean
, 当然上层构建Call
时候,Callback
也必须是 Call<MyBean>
|
|
仔细的朋友会发现有的地方用Call,有的地方用Observable
,如果结合了RxJava就是用后者接收了,这里不关乎什么方式。
上面的代码片段中显示的代码初始化(RequestBody
和description
), 以及如何使用文件上传API。正如刚开始已经提到的, 从OkHttp 的RequestBody
类中,需要两个RequestBody.create()
方法
除了Body描述, 必须将添加文件包装成MultipartBody
的实例。这就是你需要使用适当的从客户端上传文件到服务端。此外, 您可以添加createFormData
中的uploadFile(Uri fileUri)方法,适合相机拍照回来上传图片的场景。
|
|
通过以上代码片段,可以构造自己的file
, 其他构建ResquestBody
的步骤同上所示,以上案列总有一款适合你的web后端。
设置 Content-Type
请注意设置的内容类型。如果你拦截底层OkHttp客户端和更改内容类型为application / json
, 你的服务器可能反序列化过程出现的问题。请确保你没有自定义更改multipart/form-data
。
upLoad图片也可以具体指明Content-Type 为 “image/jpg”格式的
|
|
上传文件到服务端示例
如果你已经有你的后端项目, 您可以依靠下面的示例代码。我们使用一个简单api 上传到服务器。此外我们告诉api 传入参数的请求, 因为我们使用的是Node.js
解析的回调函数,我们记录每个字段来显示其输出。
Android客户端收到返回类型的字符串, 我们将接收到的上传成功的状态的回调。当然你可以处理也可以不处理状态。下面你将看到一个成功的请求的输出端和有效载荷的解析。第一个空对象。之后,你可以看到字段只描述作为请求的一部分。接着可以收到文件描述,文件大小,文件昵称和保存路径。
服务器解析有效数据的日志
Null
{ description: [ 'hello, this is description speaking' ] }
{ picture:
[ { fieldName: 'picture',
originalFilename: '20160312_095248.jpg',
path: '/var/folders/rq/q_m4_21j3lqf1lw48fqttx_80000gn/T/X_sxX6LDUMBcuUcUGDMBKc2T.jpg',
headers: [Object],
size: 39369 } ] }
回顾
文件上传是应用程序中必不可却少的功能, 你可以将此功能集成在您的应用程序使用。本文指导您完成你的Android程序上报文件到您的后端服务器的第一个步骤。
文件上传和下载进度实现,请继续关注后续文章!
源码:https://github.com/Tamicer/Novate
Retrofit 2.0+RxJava系列请阅读
- Novate网络库:Retrofit2.0和RxJava1.x的又一次完美封装。
- Retrofit 2.0 超能实践(九)Rxjava结合Retrofit,如何优雅的取消请求!
- Retrofit 2.0 超能实践(八)源码解析,玩转IOC和AOP, 徒手实现属于你的Retrofit框架
- Retrofit 2.0 超能实践(七)Rxjava +Retrofit 你需要掌握的几个经典技巧
- Retrofit 2.0 超能实践(六)基于Retrofit2.0+RxJava 封装的超好用的RetrofitClient工具类
- Retrofit 2.0 超能实践(五),动态Okhttp对Request统一添加header和Parameter
- Retrofit 2.0 超能实践(四),实现大文件多线程断点下载
- Retrofit 2.0 超能实践(三),轻松实现多文件/图片/Json字符串/表单提交上传
- Retrofit 2.0 超能实践(二),Okhttp完美同步持久Cookie实现免登录
- Retrofit 2.0 超能实践(一),完美支持加密Https传输