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实现多图片/文件、图文上传功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • Android使用Retrofit仿微信多张图片拍照上传

    Android 仿照微信发说说,既能实现拍照,选图库,多图案上传,使用Retrofit技术. 使用方法:详见http://www.jb51.net/article/103009.htm 项目的运行效果: 服务器端接收文件的action UploadFile.java @Controller public class UploadFile extends ActionSupport { /** * */ private static final long serialVersionUID = 1L

  • Android app开发中Retrofit框架的初步上手使用

    Retrofit 2.0 先来说一下Retrofit 2.0版本中一些引人注意的地方. 在Retrofit 2.0中,最大的改动莫过于减小库的体积,首先,Retrofit 2.0去掉了对所有的HTTP客户端的兼容,而钟情于OkHttpClient一个,极大地减少了各种适配代码,原因一会儿说;其次,拆库,比如将对RxJava的支持设置为可选(需要额外引入库):再比如将各个序列化反序列化转换器支持设置为可选(需要额外引入库).于2.0抛弃HttpClient和HttpURLConnection,为了

  • Android中Retrofit 2.0直接使用JSON进行数据交互

    之前使用Retrofit都是将JSON串转化为POJO对象,针对不同的业务协议,定义相应的接口和参数列表.但是此种方式一般用在自己内部协议基础上,具体大的项目中,有些第三方的集成功能,一般都采用统一的方式即请求JSON和回应JSON进行数据交互,不可能每个第三方协议都会去定义与协议相应的POJO对象. HTTP肯定有GET和POST方法,先定义Retrofit Api的interface: package com.hdnetworklib.network.http; import java.ut

  • 简略分析Android的Retrofit应用开发框架源码

    面对一个项目,对于Android应用开发框架的选择,我想过三种方案: 1.使用Loader + HttpClient + GreenDao + Gson + Fragment,优点是可定制性强,由于使用Google家自己的Loader和LoaderManager,代码健壮性强. 缺点是整套代码学习成本较高,使用过程中样板代码较多,(比如每一个Request都需要产生一个新类) 2.Volley,作为Google在IO大会上得瑟过的一个网络库,其实不算什么新东西(2013 IO发布),使用较为简单

  • Android Retrofit 2.0框架上传图片解决方案

    本文为大家分享了 Android Retrofit 2.0框架上传图片解决方案,具体内容如下 1.单张图片的上传 /** * 上传一张图片 * @param description * @param imgs * @return */ @Multipart @POST("/upload") Call<String> uploadImage(@Part("fileName") String description, @Part("file\&qu

  • Android中Retrofit+OkHttp进行HTTP网络编程的使用指南

    Retrofit介绍: Retrofit(GitHub主页https://github.com/square/okhttp)和OkHttp师出同门,也是Square的开源库,它是一个类型安全的网络请求库,Retrofit简化了网络请求流程,基于OkHtttp做了封装,解耦的更彻底:比方说通过注解来配置请求参数,通过工厂来生成CallAdapter,Converter,你可以使用不同的请求适配器(CallAdapter), 比方说RxJava,Java8, Guava.你可以使用不同的反序列化工具

  • Android Retrofit和Rxjava的网络请求

    Android  Retrofit和Rxjava的网络请求 去年的时候好多公司就已经使用Rxjava和Retrofit了,最近自自己学习了一下,感觉真的是很好用,让自己的网络请求变得更简单了,而且封装性极强. 首先做一下准备工作,导入需要引用的文件 compile 'com.android.support:appcompat-v7:25.1.0' testCompile 'junit:junit:4.12' compile 'io.reactivex:rxjava:1.1.0' compile

  • Android Retrofit 中文乱码问题的解决办法

    Android Retrofit 中文乱码问题的解决办法 使用retrofit和rxjava,提交数据时需注意,当数据中有中文时,传到后台,可能会是乱码,需处理: 解决: 1.GET请求改成POST; 2.参数Field改成Query 3.加上@FormUrlEncoded 如下: @FormUrlEncoded @POST("/test/test") Call<Response> register(@Field("name") String name)

  • android Retrofit2+okHttp3使用总结

    使用前准备 Build.gradle文件配置 dependencies配置 compile 'com.squareup.retrofit2:retrofit:2.0.0' compile 'com.squareup.retrofit2:converter-gson:2.0.0' compile 'com.squareup.okhttp3:logging-interceptor:3.2.0' 网络框架搭建 服务创建类封装(HTTP): public class ServiceGenerator {

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

    什么是 Retrofit ? Retrofit是Square开发的一个Android和Java的REST客户端库.这个库非常简单并且具有很多特性,相比其他的网络库,更容易让初学者快速掌握.它可以处理GET.POST.PUT.DELETE-等请求,还可以使用picasso加载图片. 一.再次膜拜下Retrofit Retrofit无论从性能还是使用方便性上都很屌!!!,本文不去介绍其运作原理(虽然很想搞明白),后面会出专题文章解析Retrofit的内部原理:本文只是从使用上解析Retrofit实现

  • asp.net图片文件的上传与删除方法

    本文实例讲述了asp.net图片文件的上传与删除方法.分享给大家供大家参考,具体如下: //上传图片 public void UpdataImage() { //获取选择的文件 string fileName = fudImage.FileName; //获取后缀名 string fileExt = Path.GetExtension(fileName); if (fileExt != ".jpg") { return; } //获取服务器端得上传的路径 string serverPa

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

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

  • jquery.uploadView 实现图片预览上传功能

    图片上传,网上有好多版本,今天也要做一个查了好多最终找到了一个uploadview 进行了一下修改 来看代码 @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> <script src=&quo

  • Vue实现带进度条的文件拖动上传功能

    1. 基本界面 <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1

  • Vue2.0结合webuploader实现文件分片上传功能

    Vue项目中遇到了大文件分片上传的问题,之前用过webuploader,索性就把Vue2.0与webuploader结合起来使用,封装了一个vue的上传组件,使用起来也比较舒爽. 上传就上传吧,为什么搞得那么麻烦,用分片上传? 分片与并发结合,将一个大文件分割成多块,并发上传,极大地提高大文件的上传速度. 当网络问题导致传输错误时,只需要重传出错分片,而不是整个文件.另外分片传输能够更加实时的跟踪上传进度. 实现后的界面: 主要是两个文件,封装的上传组件和具体的ui页面,上传组件代码下面有列出来

  • Jeeplus-vue 实现文件的上传功能

    前端 一.uploadList.vue ① 首先在页面中添加一个放置图片的位置,来展示图片 <el-table-column prop="upload" label="高校证明材料"> <template slot-scope="scope" v-if="scope.row.upload"> <el-image style="height: 30%;width:30%;margin-le

  • asp.net利用ashx文件实现文件的上传功能

    原来以为文件上传是一个比较简单的功能,结果搞了一个晚上才搞定~这里主要介绍两种方法实现. 方法一:Form表单提交 html代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>上传文件</title> <script src="Scripts/jquery-1.11.3.min.js"></scri

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

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

  • angularjs客户端实现压缩图片文件并上传实例

    主要是利用html5的canvas来进行图片的压缩,然后转化为dataURL,再有dataURL转化为Blob文件,Blob对象可以直接赋值给Formdata. app.service('Util', function($q) { var dataURItoBlob = function(dataURI) { // convert base64/URLEncoded data component to raw binary data held in a string var byteString

随机推荐