通过对Retrofit2.0的前两篇的基础入门和案例实践,掌握了怎么样使用Retrofit访问网络,加入自定义header头,包括加入SSL证书,基本的调试基础,cookie同步问题,但很多场景需求是需要文件的上传的,今天主题就来分享怎么用Retrofit2.0+ RxJava 上传文件和图片,表单,包括上传Json等。其实有无rxjava,Retrofit的图片上传姿势都一样,api返回的call换成 Observable即可

使用 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() RequestBody file);

或者 :

@Multipart
@POST()
Observable<ResponseBody> uploads(
@Url String url,
@Part() MultipartBody.Part 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,
@PartMap() Map<String, RequestBody> maps);

图文同时上报

Part方式

@Multipart
@POST("upload/")
Call<ResponseBody> register(
@FieldMap Map<String , String> usermaps,
@Part("avatar\"; filename=\"avatar.jpg") RequestBody avatar,
);

扩展一下 将url动态化:

@Multipart
@POST
Observable<ResponseBody> uploadFileWithPartMap(
@Url() String url,
@PartMap() Map<String, RequestBody> partMap,
@Part("file") MultipartBody.Part file);

注意如果你用retrofit2.0以上的版本请看下面姿势,否则会如下抛异常!MultipartBody.Part的参数不能指定part() 的Key。

java.lang.IllegalArgumentException: @Part parameters using the MultipartBody.Part must not include a part name in the annotation. (parameter #)
@Multipart
@POST
Observable<ResponseBody> uploadFileWithPartMap(
@Url() String url,
@PartMap() Map<String, RequestBody> partMap,
@Part MultipartBody.Part file);

java代码:

String token ="dsdsddadad244";
RequestBody requestFile =
RequestBody.create(MediaType.parse("multipart/form-data"), file); // MultipartBody.Part is used to send also the actual file name
MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", file.getName(), requestFile); // create a map of data to pass along
RequestBody tokenBody = RequestBody.create(
MediaType.parse("multipart/form-data"), token); HashMap<String, RequestBody> map = new HashMap<>();
map.put("token", tokenBody); Call<ResponseBody> call = service.uploadFileWithPartMap(url, requestBody );
// 执行
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());
}
});

更简单的用Body方式:

 @POST()
Call<ResponseBody> upLoad(
@Url() String url,
@Body RequestBody Body);

如果支持RxJava就是:

@POST()
Observable<ResponseBody> upLoad(
@Url() String url,
@Body RequestBody Body);
```` Java代码: //构建body
RequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("name", name)
.addFormDataPart("psd", psd)
.addFormDataPart("file", file.getName(), RequestBody.create(MediaType.parse("image/*"), file))
.build(); //如果和rxjava1.x , call就换成 Observable
Call<ResponseBody> call = service.upload(url, requestBody );
// 执行
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("upload/")
Call<ResponseBody> register(
@Body RequestBody body
); Java代码: RequestBody requestFile =
RequestBody.create(MediaType.parse("multipart/form-data"), file); Call<ResponseBody> call = service.register(body);
Response<ResponseBody> response = call.execute(); ##Json提交 **上传Json** @POST("/uploadJson")
Observable<ResponseBody> uploadjson(
@Body RequestBody jsonBody); **upLoadJson 也可以具体指明Content-Type 为 “application/json”格式的** 具体组装我们的RequestBody则可以这样: RequestBody body=
RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"), jsonString); 接着可以这样调用: // 执行请求
Call<ResponseBody> call = service.uploadJson(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());
}
});
} 至于服务器返回什么类型的**model**, 开发者可以自定义, 譬如你可以把APi 中的 ResponseBody 指定为你自己的`javaBean`, 当然上层构建Call时候,`Callback`也必须是 `Call<MyBean>` @POST("/uploadJson")
Call<MyBean> uploadjson(
@Body RequestBody jsonBody); 仔细的朋友会发现有的地方用Call,有的地方用Observable,如果结合了RxJava就是用后者接收了,这里不关乎什么方式。 上面的代码片段中显示的代码初始化(RequestBody 和description), 以及如何使用文件上传API。正如刚开始已经提到的, 从OkHttp 的RequestBody类中,需要两个RequestBody.create()方法 除了Body描述, 必须将添加文件包装成MultipartBody的实例。这就是你需要使用适当的从客户端上传文件到服务端。此外, 您可以添加createFormData中的uploadFile(Uri fileUri)方法,适合相机拍照回来上传图片的场景。 public static File getFile(Context context, Uri uri) {
if (uri != null) {
String path = getPath(context, uri);
if (path != null && isLocal(path)) {
return new File(path);
}
}
return null;
} 通过以上代码片段,可以构造自己的file, 其他构建ResquestBody的步骤同上所示,以上案列总有一款适合你的web后端。 设置 Content-Type
========================= 请注意设置的内容类型。如果你拦截底层OkHttp客户端和更改内容类型为application / json, 你的服务器可能反序列化过程出现的问题。请确保你没有自定义更改multipart/form-data。 **upLoad图片也可以具体指明Content-Type 为 “image/jpg”格式的** RequestBody requestFile =
RequestBody.create(MediaType.parse("image/jpg"), mFile); 上传文件到服务端示例
====================================== 如果你已经有你的后端项目, 您可以依靠下面的示例代码。我们使用一个简单api 上传到服务器。此外我们告诉api 传入参数的请求, 因为我们使用的是Node.js 解析的回调函数,我们记录每个字段来显示其输出。 method: 'POST',
path: '/upload',
config: {
payload: {
maxBytes: ,
output: 'stream',
parse: false
},
handler: function(request, reply) {
var multiparty = require('multiparty');
var form = new multiparty.Form();
form.parse(request.payload, function(err, fields, files) {
console.log(err);
console.log(fields);
console.log(files); return reply(util.inspect({fields: fields, files: files}));
});
}} 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: } ] } ---------------------------------
回顾
== 文件上传是应用程序中必不可却少的功能, 你可以将此功能集成在您的应用程序使用。本文指导您完成你的Android程序上报文件到您的后端服务器的第一个步骤。 文件上传和下载进度实现,请继续关注后续文章! **源码:[https://github.com/Tamicer/Novate](https://github.com/Tamicer/Novate)** Retrofit .0系列请阅读简书
更多技术文章请关注码小白 **Retrofit 2.0+RxJava系列请阅读** - [Retrofit 2.0(一) 超能实践,完美支持Https传输](http://blog.csdn.net/sk719887916/article/details/51597816) - [Retrofit2.(二) 完美同步Cookie实现免登录](http://blog.csdn.net/sk719887916/article/details/51700659) - [Retrofit 2.0 超能实践(三),轻松实现文件/图片上传](http://blog.csdn.net/sk719887916/article/details/51700659) - [Retrofit 2.0 超能实践(四),完成大文件断点下载](http://www.jianshu.com/p/582e0a4a4ee9) - [基于Retrofit2.+RxJava 封装的超好用的RetrofitClient工具类(六)](http://blog.csdn.net/sk719887916/article/details/51958010) - [玩转IOC,教你徒手实现自定义的Retrofit框架(七)](http://blog.csdn.net/sk719887916/article/details/51957819) - [Retrofit,Okhttp对每个Request统一动态添加header和参数(五)](http://blog.csdn.net/sk719887916/article/details/52132106)
- [Rxjava和Retrofit 需要掌握的几个实用技巧,缓存问题和统一对有无网络处理问题(八)](http://blog.csdn.net/sk719887916/article/details/52132106)
- [Novate:对Retrofit2.0的又一次完美改进加强!(九)](http://blog.csdn.net/sk719887916/article/details/52195428) 第一时间获取技术文章请关注微信公众号! ![开发者技术前线](http://upload-images.jianshu.io/upload_images/2022038-a7b567ef3a0b0d1f.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
>Tamic : http://www.jianshu.com/users/3bbb1ddf4fd5/

Retrofit 2.0 轻松实现多文件/图片上传/Json字符串/表单的更多相关文章

  1. Retrofit 2.0 超能实践(三),轻松实现文件/多图片上传/Json字符串

    文:http://blog.csdn.net/sk719887916/article/details/51755427 Tamic 简书&csdn同步 通过前两篇姿势的入门 Retrofit ...

  2. 基于ASP.Net +easyUI框架上传图片,实现图片上传,提交表单

    <body> <link href="../../Easyui/themes/easyui.css" rel="stylesheet" typ ...

  3. WebUploader文件图片上传插件的使用

    最近在项目中用到了百度的文件图片上传插件WebUploader.分享给大家 需要在http://fex.baidu.com/webuploader/download.html点击打开链接下载WebUp ...

  4. commons-fileload图片文件上传工具 , servlet文件图片上传案列

    本案列是java  maven工程小项目,提供个大家学习! 1.在pom.xml文件中导入依赖: <!--文件上传依赖--><dependency> <groupId&g ...

  5. layui框架实现多图片手动上传和随表单提交方法

    首先在官方文档并没有手动上传的说明文档,这里手动实现上传原理是:在表单中有三个按钮,分别是上传图片按钮.隐藏上传按钮.表单提交按钮,点击上传图片按钮之后,图片添加在前端但是并没有真正的上传,而是在点击 ...

  6. [iOS AFNetworking框架实现HTTP请求、多文件图片上传下载]

    简单的JSON的HTTP传输就不说了,看一个简单的DEMO吧. 主要明白parameters是所填参数,类型是字典型.我把这部分代码封装起来了,以便多次调用.也许写在一起更清楚点. #pragma m ...

  7. WebApi2 文件图片上传下载

    Asp.Net Framework webapi2 文件上传与下载 前端界面采用Ajax的方式执行 一.项目结构 1.App_Start配置了跨域访问,以免请求时候因跨域问题不能提交.具体的跨域配置方 ...

  8. 关于富文本编辑器—UEditor(java版)的使用,以及如何将UEditor的文件/图片上传路径改成绝对路径

    突然发现好久没写博客了,感觉变懒了,是要让自己养成经常写文章的习惯才行.既可以分享自己的所学,和所想,和大家一起讨论,发现自己的不足的问题. 大家可能经常会用到富文本编辑器,今天我要说的是UEdito ...

  9. TP5.0整合webuploader实现多图片上传功能

    在https://github.com/fex-team/webuploader 下载webuploader并解压,解压后放到public里面.其中我把解压缩后的文件夹改名为webuploader,放 ...

随机推荐

  1. Ubuntu Linux 使用桂电校园网 上网

    2016年9月1日 星期四 桂电校园网今天升级新的出校器,旧的出校器已经不能使用,所以本篇博客已经过期,下面的方法已经不能让Ubuntu使用桂电校园网上外网了.详细的原因,请到这个网站查看:校园网计费 ...

  2. Learning Python 008 正则表达式-002 findall()方法

    Python 正则表达式 - findall()方法 重点 findall()方法的使用 - 程序讲解 简单的符号的使用 正则表达式的库文件是re,先导入库文件: import re .的使用举例 # ...

  3. mac下已装virtualbox运行genymotion还报错找不到虚拟机的解决办法

    sudo ln -s /usr/local/bin/VBoxManage /usr/bin/VBoxManage  

  4. python笔记——均值、方差、中位数计算

    from __future__ import print_function # 均值计算 data = [3.53, 3.47, 3.51, 3.72, 3.43] average = float(s ...

  5. 1.3 xss原理分析与剖析(4)

    0×01 URL编码 URL只允许用US-ASCII字符集中可打印的字符(0×20—0x7x),其中某些字符在HTTP协议里有特殊的意义,所以有些也不能使用.这里有个需要注意的,+加号代表URL编码的 ...

  6. EIP权限工作流平台总结-3后端框架

    1.预览地址:www.eipflow.com (1) 权限工作流:www.demo.eipflow.com/Account/Login (2) 基础权限版:www.auth.eipflow.com/A ...

  7. fatal: Authentication failed (二)

    一.前言 前面一段时间写了一篇解决 git 上传代码出现的权限验证问题,还是没有很好的解决.现在还了方式,具体步骤如下: 二.操作流程 我们在上传代码到服务器,我们都需要安装 Git 版本控制.在安装 ...

  8. JavaScript -- 常用的数组及字符串方法

    数组 var arr= new Array(); arr.push(); //在数组尾部添加一个元素,返回新的长度 *原数组发生变化 arr.pop(); //删除最后一个元素,返回的是被删除的元素 ...

  9. 解读人:李思奇,Development of a sensitive, scalable method for spatial, cell-type-resolved proteomics of the human brain. (一种用于研究人类大脑基于空间或细胞类型的蛋白质组学的灵敏方法)

    发表时间:(2019年4月) 一. 概述: 本文报道了一种可研究人类大脑组织中特定神经细胞的蛋白质组学的方法.作者通过激光捕获显微切割技术(LCM)从逝者大脑中分离出目的神经元细胞,接着尝试了一系列不 ...

  10. Mol Cell Proteomics. |赵赟| 全面地分析个人尿蛋白质组学的变化揭示出不同的性别变化

    大家好,本周分享的是发表在Molecular & Cellular Proteomics上的一篇关于人的尿蛋白质组学的文章,题目是Comprehensive analysis of indiv ...