Android Retrofit 上传文件图片
2016-12-20 18:34
330 查看
通过前两篇姿势的入门
Retrofit 2.0
超能实践,完美支持Https传输
Retrofit2.0
完美同步Cookie实现免登录
通过对Retrofit2.0的前两篇的基础入门和案例实践,掌握了怎么样使用Retrofit访问网络,加入自定义header头,包括加入SSL证书,基本的调试基础,cookie同步问题,但很多场景需求是需要文件的上传的,今天主题就来分享怎么用Retrofit2.0 上传文件和图片,表单,包括上传Json等。
具体用法。
先看一个基本的用法:
或者:
扩展一下:
java代码:
更简单的用Body方式:
Java代码:
此种方式让你很好的解决了用户注册问题,包含用户全部信息和头像,完美解决你想用表单一起将文字和图片一起提交的情况!
Java代码:
upLoadJson 也可以具体指明Content-Type 为 “application/json”格式的
具体组装我们的RequestBody则可以这样:
接着可以这样调用:
}
至于服务器返回什么类型的model, 开发者可以自定义, 譬如你可以把APi 中的 ResponseBody 指定为你自己的
仔细的朋友会发现有的地方用Call,有的地方用Observable,如果结合了RxJava就是用后者接收了,这里不关乎什么方式。
上面的代码片段中显示的代码初始化(RequestBody 和description), 以及如何使用文件上传API。正如刚开始已经提到的, 从OkHttp 的RequestBody类中,需要两个RequestBody.create()方法
除了Body描述, 必须将添加文件包装成MultipartBody的实例。这就是你需要使用适当的从客户端上传文件到服务端。此外, 您可以添加createFormData中的uploadFile(Uri fileUri)方法,适合相机拍照回来上传图片的场景。
通过以上代码片段,可以构造自己的file, 其他构建ResquestBody的步骤同上所示,以上案列总有一款适合你的web后端。
upLoad图片也可以具体指明Content-Type 为 “image/jpg”格式的
解析的回调函数,我们记录每个字段来显示其输出。
Android客户端收到返回类型的字符串, 我们将接收到的上传成功的状态的回调。当然你可以处理也可以不处理状态。下面你将看到一个成功的请求的输出端和有效载荷的解析。第一个空对象。之后,你可以看到字段只描述作为请求的一部分。接着可以收到文件描述,文件大小,文件昵称和保存路径。
源码:https://github.com/Tamicer/Novate
Retrofit 2.0系列请阅读简书
更多技术文章请关注码小白
Retrofit 2.0+RxJava系列请阅读
Retrofit 2.0(一) 超能实践,完美支持Https传输
Retrofit2.0(二) 完美同步Cookie实现免登录
Retrofit 2.0 超能实践(三),轻松实现文件/图片上传
Retrofit 2.0 超能实践(四),完成大文件断点下载
基于Retrofit2.0+RxJava 封装的超好用的RetrofitClient工具类(六)
玩转IOC,教你徒手实现自定义的Retrofit框架(七)
Retrofit,Okhttp对每个Request统一动态添加header和参数(五)
Rxjava和Retrofit 需要掌握的几个实用技巧,缓存问题和统一对有无网络处理问题(八)
Novate:对Retrofit2.0的又一次完美改进加强!(九)
Retrofit 2.0
超能实践,完美支持Https传输
Retrofit2.0
完美同步Cookie实现免登录
通过对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方式@Multipart @POST("upload/") Call<ResponseBody> register( @FieldMap Map<String , String> usermaps, @Part("avatar\\\\\\\\\\\\\\\\"; filename=\\\\\\\\\\\\\\\\"avatar.jpg") RequestBody avatar, );
扩展一下:
@Multipart @POST Observable<ResponseBody> uploadFileWithPartMap( @Url() String url, @PartMap() Map<String, RequestBody> partMap, @Part("file") MultipartBody.Part file);
java代码:
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);
Java代码:
//构建body RequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM) .addFormDataPart("name", name) .addFormDataPart("name", psd) .addFormDataPart("file", file.getName(), RequestBody.create(MediaType.parse("image/*"), file)) .build(); 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: 209715200, 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: 39369 } ] }
回顾
文件上传是应用程序中必不可却少的功能, 你可以将此功能集成在您的应用程序使用。本文指导您完成你的Android程序上报文件到您的后端服务器的第一个步骤。源码:https://github.com/Tamicer/Novate
Retrofit 2.0系列请阅读简书
更多技术文章请关注码小白
Retrofit 2.0+RxJava系列请阅读
Retrofit 2.0(一) 超能实践,完美支持Https传输
Retrofit2.0(二) 完美同步Cookie实现免登录
Retrofit 2.0 超能实践(三),轻松实现文件/图片上传
Retrofit 2.0 超能实践(四),完成大文件断点下载
基于Retrofit2.0+RxJava 封装的超好用的RetrofitClient工具类(六)
玩转IOC,教你徒手实现自定义的Retrofit框架(七)
Retrofit,Okhttp对每个Request统一动态添加header和参数(五)
Rxjava和Retrofit 需要掌握的几个实用技巧,缓存问题和统一对有无网络处理问题(八)
Novate:对Retrofit2.0的又一次完美改进加强!(九)
相关文章推荐
- 【Android实战】----基于Retrofit实现多图片/文件、图文上传
- 【Android实战】----基于Retrofit实现多图片/文件、图文上传
- 【Android实战】----基于Retrofit实现多图片/文件、图文上传
- 【Android实战】----基于Retrofit实现多图片/文件、图文上传
- Android Retrofit实现多图片/文件、图文上传功能
- [android]模拟Http表单,实现本地文件(图片等)上传到服务器端
- Android 通过HTTP POST 上传图片文件
- android Volley 上传文件上传图片
- 【Android】图片(文件)上传的请求分析结构
- Android图片文件上传实例
- Android中使用又拍云存储来上传文件(包括图片、音频和视频等)
- Android 上传文件,图片
- Android 上传文件,图片。以及服务器端接收相关。
- Android文件图片上传的详细讲解(一)HTTP multipart/form-data 上传报文格式实现手机端上传GOOD
- Android 上传文件,图片。以及服务器端接收相关
- android 上传文件图片
- Android 上传文件,图片。以及服务器端接收相关。
- android文件上传示例分享(android图片上传)
- Android文件图片上传的详细讲解(一)HTTP multipart/form-data 上传报文格式实现手机端上传
- Android Webview实现图片、文件上传及启动相机功能