安卓学习笔记---Retrofit2.0 实现图文(参数+图片)上传方法总结
来源:互联网 发布:java四舍五入取整 编辑:程序博客网 时间:2024/05/17 01:01
转载博客地址:
http://www.jb51.net/article/120237.htm
最近项目里用到了类似图文上传的功能,以前都是封装OkHttp的文件上传功能,这次想换个姿势,想用Retrofit2.0实现这样的功能,本来以为挺简单的,没想到进入了深坑,连续调整了好几种姿势都报了同一个错,接着网上类似的文章找了一大推,讲得都是模棱两可,或者对多参数格式不够友好,最后还是去看了相关的源码,自己把这个问题提出来解决了,在这里记录一下。
一、定义网络请求接口
上面定义了一个接口用于上传文件请求,有几个注解需要说明一下, @Multipart这是Retrofit专门用于文件上传的注解,需要配合@POST一起使用。
方法postGoodsReturnPostEntitys(@PartMap Map<String, RequestBody> map, @Part List<MultipartBody.Part> parts)第一个参数使用注解@PartMap用于多参数的情况,如果是单个参数也可使用注解@Part。
在类型Map<String, RequestBody>中,Map第一个泛型String是服务器接收用于文件上传参数字段的Key,第二个泛型RequestBody是OkHttp3包装的上传参数字段的Value,这也是图文上传成功的关键所在。在后面会具体说到。
第二个参数使用注解@Part用于文件上传,多文件上传使用集合类型List<MultipartBody.Part>,单文件可以使用类型MultipartBody.Part,具体的使用同样后面讲。
这里着重说明一下,postGoodsReturnPostEntitys(@PartMap Map<String, RequestBody> map, @Part List<MultipartBody.Part> parts)方法参数这样写纯属个人习惯,你也可以直接使用一个参数postGoodsReturnPostEntitys(@PartMap Map<String, RequestBody> map),不过后面对RequestBody的处理方式也要跟着变化,这里就不详细说了,只会介绍上面这种简便清晰的方式。
二、初始化Retrofit
为了演示,Retrofit封装比较简陋,为的是查看网络拦截,就不详细说了。
三、发起文件上传请求
上面的params和fileList都是构造的伪代码,需要根据自己项目的业务需求改变。
下面是上传文件成功第一个关键,对参数请求头(姑且叫这个名字,对应Retrofit上传文件时参数那部分请求头,下文件(图片)请求头同理,对应文件那部分请求头)的content-type赋值,使用convertToRequestBody()方法。
因为GsonConverterFactory.create()转换器的缘故,会将参数请求头的content-type值默认赋值application/json,如果没有进行这步转换操作,就可以在OKHttp3的日志拦截器中查看到这样的赋值,这样导致服务器不能正确识别参数,导致上传失败,所以这里需要对参数请求头的content-type设置一个正确的值:text/plain。
下面是上传文件成功第二个关键的地方,将文件(图片)请求头的content-type使用方法filesToMultipartBodyParts()对其赋值"image/png",并返回MultipartBody.Part集合。
说到底,还是对参数请求头和文件(图片)请求头的content-type属性赋值处理,不要让Retrofit 默认赋值,这里才是关键。
根据以上信息,自己写的方法图片上传和文件上传
//图片上传接口 @Multipart用于文件上传的注解,需要配合@POST一起使用@Multipart@POST("upload.jhtml")Observable<ApiResponse<ImageUrl>> fileUploadImage(@PartMap Map<String, RequestBody> map, @Part MultipartBody.Part part);//文件上传接口@Multipart@POST("upload.jhtml")Observable<ApiResponse<PlayRecord>> fileUploadPlayRecord(@PartMap Map<String, RequestBody> map, @Part MultipartBody.Part part);
图片上传示例
Map<String, RequestBody> params = new HashMap<>();//以下参数是伪代码,参数需要换成自己服务器支持的params.put("token", RequestBodyUtil.convertToRequestBody(SharedPreferenceUtil.getString("token")));params.put("fileType",RequestBodyUtil.convertToRequestBody("image"));File file = new File(imageUrl);RequestBody requestBody = RequestBody.create(MediaType.parse("image/*"), file);MultipartBody.Part part = MultipartBody.Part.createFormData("file", file.getName(), requestBody);final UserService userService = RetrofitProvider.getInstance().create(UserService.class);emit(userService.fileUploadImage(params, part), new ApiResponseListener<ImageUrl>() { @Override public void onApiSuccess(ImageUrl imageUrlData) { LoggerUtil.i("UserUpdate", "headImagePath-->" + imageUrlData.getUrl()); } @Override public void onApiFail(int errorCode, String errorMessage) { ToastUtil.showToast(UserUpdateActivity.this,errorMessage); }});
文件上传
final File file = new File(Contant.PATH);if (!file.exists()) { file.mkdirs();}File fileSave = new File(Contant.PATH + "aa.txt");if (!fileSave.exists()) { try { fileSave.createNewFile(); print("测试的数据"); } catch (IOException e) { e.printStackTrace(); }}Map<String, RequestBody> params = new HashMap<>();//以下参数是伪代码,参数需要换成自己服务器支持的params.put("token", RequestBodyUtil.convertToRequestBody(SharedPreferenceUtil.getString("token")));params.put("fileType",RequestBodyUtil.convertToRequestBody("file"));params.put("action", RequestBodyUtil.convertToRequestBody("result"));params.put("memberId",RequestBodyUtil.convertToRequestBody(String.valueOf(LoginControllor.getLoginMember().getMember().getId())));params.put("msId", RequestBodyUtil.convertToRequestBody(String.valueOf(forId)));RequestBody requestBodyPart = RequestBody.create(MediaType.parse("multipart/form-data; charset=utf-8"), fileSave);MultipartBody.Part part = MultipartBody.Part.createFormData("file", fileSave.getName(), requestBodyPart);UserService userService = RetrofitProvider.getInstance().create(UserService.class);emit(userService.fileUploadPlayRecord(params, part), new ApiResponseListener<PlayRecord>() { @Override public void onApiSuccess(PlayRecord playRecord) { LoggerUtil.i("Play", "playRecord-->" + playRecord); } @Override public void onApiFail(int errorCode, String errorMessage) { ToastUtil.showToast(Play.this,errorMessage); }});
- 安卓学习笔记---Retrofit2.0 实现图文(参数+图片)上传方法总结
- Retrofit2.0 上传图片
- retrofit2.0,上传图片
- Android Retrofit 实现(图文上传)文字(参数)和多张图片一起上传
- Retrofit2.0轻松实现上传
- retrofit2.0图片上传filename问题
- Retrofit2.0:上传图片到PHP
- Retrofit2.0上传图片文件件整理
- (安卓)图片上传
- retrofit2上传图片
- Rxjava2+Retrofit2上传图片加参数失败问题解决
- android开发:使用Retrofit2框架,如果上传图片+json参数?
- 创建 Js图片上传实现方法总结
- retrofit2上传文件总结
- Android Retrofit2.0 学习笔记
- Retrofit2 学习笔记(一)
- Retrofit2 学习笔记(二)
- retrofit2.0 使用笔记-文件上传功能
- C语言--函数指针
- 练习1-8
- vue-模态组件
- Android 基于google Zxing实现二维码、条形码扫描,仿微信二维码扫描效果
- 1002.Fire Net
- 安卓学习笔记---Retrofit2.0 实现图文(参数+图片)上传方法总结
- 聊天室项目相关内容知识问答
- Android 开源框架ActionBarSherlock 和 ViewPager 仿网易新闻客户端
- eclipse汉化
- 007
- MySQL数据库的热备份和冷备份的优缺点
- Android 异步加载图片,使用LruCache和SD卡或手机缓存,效果非常的流畅
- 【OPNET小问题】统计量显示收发数据数量不匹配以及如何导出统计量数据
- Android Service与Activity之间通信的几种方式