Android Retrofit实现多图片/文件、图文上传功能

什么是 Retrofit ?

Retrofit是Square开发的一个Android和Java的REST客户端库。这个库非常简单并且具有很多特性,相比其他的网络库,更容易让初学者快速掌握。它可以处理GET、POST、PUT、DELETE…等请求,还可以使用picasso加载图片。

一、再次膜拜下Retrofit

Retrofit无论从性能还是使用方便性上都很屌!!!,本文不去介绍其运作原理(虽然很想搞明白),后面会出专题文章解析Retrofit的内部原理;本文只是从使用上解析Retrofit实现多图片/文件、图文上传的功能。

二、概念介绍

1)注解@Multipart

从字面上理解就是与多媒体文件相关的,没错,图片、文件等的上传都要用到该注解,其中每个部分需要使用@Part来注解。。看其注释

/** * Denotes that the request body is multi-part. Parts should be declared as parameters and * annotated with {@link Part @Part}. */

2)注解@PartMap

当然可以理解为使用@PartMap注释,传递多个Part,以实现多文件上传。注释

/** * Denotes name and value parts of a multi-part request. * <p> * Values of the map on which this annotation exists will be processed in one of two ways: * <ul> * <li>If the type is {@link okhttp3.RequestBody RequestBody} the value will be used * directly with its content type.</li> * <li>Other object types will be converted to an appropriate representation by using * {@linkplain Converter a converter}.</li> * </ul> * <p> * <pre><code> * @Multipart * @POST("/upload") * Call<ResponseBody> upload( * @Part("file") RequestBody file, * @PartMap Map<String, RequestBody> params); * </code></pre> * <p> * A {@code null} value for the map, as a key, or as a value is not allowed. * * @see Multipart * @see Part */

3)RequestBody

从上面注释中就可以看到参数类型是RequestBody,其就是请求体。文件上传就需要参数为RequestBody。官方使用说明如下http://square.github.io/retrofit/

Multipart parts use one of Retrofit's converters or they can implement RequestBody to handle their own serialization.

四、基本实现

了解了以上概念,下面就一一实现

1)接口定义

public interface IHttpService { @Multipart @POST("nocheck/file/agree.do") Call<BaseBean> upLoadAgree(@PartMap Map<String, RequestBody>params); }

BaseBean是根据服务端返回数据进行定义的,这个使用时可以根据自有Server定义。

2)Retrofit实现

/** * Created by DELL on 2017/3/16. * 上传文件用(包含图片) */ public class RetrofitHttpUpLoad { /** * 超时时间60s */ private static final long DEFAULT_TIMEOUT = 60; private volatile static RetrofitHttpUpLoad mInstance; public Retrofit mRetrofit; public IHttpService mHttpService; private Map<String, RequestBody> params = new HashMap<String, RequestBody>(); private RetrofitHttpUpLoad() { mRetrofit = new Retrofit.Builder() .baseUrl(UrlConfig.ROOT_URL) .client(genericClient()) .addConverterFactory(GsonConverterFactory.create()) .build(); mHttpService = mRetrofit.create(IHttpService.class); } public static RetrofitHttpUpLoad getInstance() { if (mInstance == null) { synchronized (RetrofitHttpUpLoad.class) { if (mInstance == null) mInstance = new RetrofitHttpUpLoad(); } } return mInstance; } /** * 添加统一超时时间,http日志打印 * * @return */ public static OkHttpClient genericClient() { HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); logging.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient httpClient = new OkHttpClient.Builder() .addInterceptor(logging) .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) .readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) .build(); return httpClient; } /** * 将call加入队列并实现回调 * * @param call 调入的call * @param retrofitCallBack 回调 * @param method 调用方法标志,回调用 * @param <T> 泛型参数 */ public static <T> void addToEnqueue(Call<T> call, final RetrofitCallBack retrofitCallBack, final int method) { final Context context = MyApplication.getContext(); call.enqueue(new Callback<T>() { @Override public void onResponse(Call<T> call, Response<T> response) { LogUtil.d("retrofit back code ====" + response.code()); if (null != response.body()) { if (response.code() == 200) { LogUtil.d("retrofit back body ====" + new Gson().toJson(response.body())); retrofitCallBack.onResponse(response, method); } else { LogUtil.d("toEnqueue, onResponse Fail:" + response.code()); ToastUtil.makeShortText(context, "网络连接错误" + response.code()); retrofitCallBack.onFailure(response, method); } } else { LogUtil.d("toEnqueue, onResponse Fail m:" + response.message()); ToastUtil.makeShortText(context, "网络连接错误" + response.message()); retrofitCallBack.onFailure(response, method); } } @Override public void onFailure(Call<T> call, Throwable t) { LogUtil.d("toEnqueue, onResponse Fail unKnown:" + t.getMessage()); t.printStackTrace(); ToastUtil.makeShortText(context, "网络连接错误" + t.getMessage()); retrofitCallBack.onFailure(null, method); } }); } /** * 添加参数 * 根据传进来的Object对象来判断是String还是File类型的参数 */ public RetrofitHttpUpLoad addParameter(String key, Object o) { if (o instanceof String) { RequestBody body = RequestBody.create(MediaType.parse("text/plain;charset=UTF-8"), (String) o); params.put(key, body); } else if (o instanceof File) { RequestBody body = RequestBody.create(MediaType.parse("multipart/form-data;charset=UTF-8"), (File) o); params.put(key + "\"; filename=\"" + ((File) o).getName() + "", body); } return this; } /** * 构建RequestBody */ public Map<String, RequestBody> bulider() { return params; } }

其中定义了Retrofit实例、还用拦截器定义了统一的超时时间和日志打印;将call加入队列并实现回调。最重要的就是添加参数:

/** * 添加参数 * 根据传进来的Object对象来判断是String还是File类型的参数 */ public RetrofitHttpUpLoad addParameter(String key, Object o) { if (o instanceof String) { RequestBody body = RequestBody.create(MediaType.parse("text/plain;charset=UTF-8"), (String) o); params.put(key, body); } else if (o instanceof File) { RequestBody body = RequestBody.create(MediaType.parse("multipart/form-data;charset=UTF-8"), (File) o); params.put(key + "\"; filename=\"" + ((File) o).getName() + "", body); } return this; }

这里就是根据传入的参数,返回不同的RequestBody。

3)使用

private void upLoadAgree() { showWaitDialog(); RetrofitHttpUpLoad retrofitHttpUpLoad = RetrofitHttpUpLoad.getInstance(); if (!StringUtil.isEmpty(pathImage[0])){ retrofitHttpUpLoad = retrofitHttpUpLoad.addParameter("pic1",new File(pathImage[0])); } if (!StringUtil.isEmpty(pathImage[1])){ retrofitHttpUpLoad = retrofitHttpUpLoad.addParameter("pic2", new File(pathImage[1])); } if (!StringUtil.isEmpty(pathImage[2])){ retrofitHttpUpLoad = retrofitHttpUpLoad.addParameter("zip", new File(pathImage[2])); } Map<String, RequestBody> params = retrofitHttpUpLoad .addParameter("status", "4") .addParameter("pickupId", tv_orderquality_pid.getText().toString()) .addParameter("cause", reason) .addParameter("connectname", et_orderquality_lxrname.getText().toString()) .addParameter("connectphone", et_orderquality_lxrphone.getText().toString()) .addParameter("details", et_orderquality_xqms.getText().toString()) .bulider(); RetrofitHttpUpLoad.addToEnqueue(RetrofitHttpUpLoad.getInstance().mHttpService.upLoadAgree(params), this, HttpStaticApi.HTTP_UPLOADAGREE); }

需要注意的是要对图片及文件路径进行判空操作,负责会报异常W/System.err: java.io.FileNotFoundException: /: open failed: EISDIR (Is a directory)

以上所述是小编给大家介绍的Android基于Retrofit实现多图片/文件、图文上传功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

时间: 2024-10-23 05:28:51

Android Retrofit实现多图片/文件、图文上传功能的相关文章

HTML5实现图片文件异步上传

原文:HTML5实现图片文件异步上传 利用HTML5的新特点做文件异步上传非常简单方便,本文主要展示JS部分,html结构.下面的代码并未使用第三发库,如果有参照,请注意一些未展现出来的代码片段.我这边的效果预览: 1.文件未选择 2.文件已选择 HTML代码部分: 思路:下面代码中我利用css的z-index属性将input="file"标签隐藏在了id=btnSelect元素下面,通过触发a标签的点击后,弹出文件选择框.下面的masklayer用于点击确认按钮后的弹出层,避免用户重

Android 高仿微信朋友圈拍照上传功能

模仿微信朋友圈发布动态,输入文字支持文字多少高度自增,有一个最小输入框高度,输入文字有限制,不过这些都很easy! 1. PhotoPicker的使用 这是一个支持选择多张图片,点击图片放大,图片之间左右滑动互相切换的库,同时支持图片删除的库,效果类似微信. (1) 添加PhotoPicker的架包 (2) 使用 选择图片:安卓6.0以后需要在代码中添加读写sd卡和相机的权限 当然清单文件中也需要添加的 PhotoPicker.builder() .setPhotoCount(maxPhoto)

ios socket 断点上传-iOS怎么用socket实现大文件断点上传功能,类似于优酷中视频上传?

问题描述 iOS怎么用socket实现大文件断点上传功能,类似于优酷中视频上传? iOS怎么用socket实现大文件断点上传功能,类似于优酷中视频上传?哪位大神给点思路或者相关demo,跪求!!! 解决方案 Android中Socket大文件断点上传Android中Socket大文件断点上传Android中Socket大文件断点上传---------------------- 解决方案二: 一遍这种都是,两边定义好命令, 文件拆分成一块一块的,每一块有一个序号,断点续传就是没上传那块接着传就行了

html5+php实现文件拖动上传功能

界面样式我是参考了一个国外的相册网站,改动不大,只是把鸟语转换成中文,以及上传时的样式也进行了改动,之所以选这个的原因就是,我很容易做扩展,它支持3种方式添加图片,一种拖拽上传,一种常规的选择文件上传,另外的就是添加网络图片.它很巧妙的把三种上传模式整合到了一起,而且你可以用IE浏览器浏览下,如果不支持HTML5,是没有拖拽上传图片的提示的,如图: 拖拽上传最重要的就是js部分的代码,它实现了70%的功能,另外30%仅仅是把图片信息提交到后台,然后做对应的处理,比如压缩啊,裁剪啊云云.所以先来看

用ASP实现文件直接上传功能

上传 引言 采用WEB技术实现B/S(浏览器/服务器)结构的管理系统是办公自动化的发展趋势.基于WEB技术的管理系统,由于开发周期短:与用户平台无关:易于实现交互式应用:能对信息进行快速.高效的收集.处理和发布,近几年来得到了迅速发展.而ASP技术由于其开发效率高.交互性好,安全性强等特点,逐渐成为开发管理系统的首选工具. 许多基于WEB的应用都涉及文件上传操作.常见的文件上传技术有:基于HTTP协议的:基于VB(或DELPHI等编程语言)开发的文件上传组件的:基于数据库技术的等等.这些方法一般

利用ASP技术实现文件直接上传功能

上传|上传 摘要: 本文首先比较了几种常见的文件上传技术,然后通过实例介绍了利用ASP技术直接实现文件上传的具体方法. 关键词:ASP:文件上传:二进制数据 引言 采用WEB技术实现B/S(浏览器/服务器)结构的管理系统是办公自动化的发展趋势.基于WEB技术的管理系统,由于开发周期短:与用户平台无关:易于实现交互式应用:能对信息进行快速.高效的收集.处理和发布,近几年来得到了迅速发展.而ASP技术由于其开发效率高.交互性好,安全性强等特点,逐渐成为开发管理系统的首选工具. 许多基于WEB的应用都

浅析Android 快速实现图片压缩与上传功能

由于最近项目更新功能比较的忙,也没时间去整理自己的知识点和管理自己的博客.在Android对手机相册中的图片的压缩和上传到服务器上,这样的功能在每个app开发中都会有这样的需求.所以今天就对android端怎么快速实现图片压缩和上传进行简单的分析. 首先需要对图片进行压缩,这方面可以使用第三方的库,我在实际的开发中使用的是 compile 'top.zibin:Luban:1.0.9'使用也比较的方便,代码如下: /** * * @param path 代表的是图片的uri路径 */ priva

Ueditor调用图片和附件上传功能

 代码如下 复制代码 <!DOCTYPE html> <html> <head> <title></title> <script src="ueditor/ueditor.config.js" type="text/javascript" charset="utf-8″></script> <script src="ueditor/ueditor.confi

jquery插件uploadify实现带进度条的文件批量上传_jquery

有时项目中需要一个文件批量上传功能时,个人认为uploadify是快速简便的解决方案,分享给大家供大家参考,具体如下 先上效果图: 具体代码如下: 在页面中如下 完整页面代码 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <!DOCTYPE html> <