热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

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

Retrofit是Square开发的一个Android和Java的REST客户端库。这个库非常简单并且具有很多特性,相比其他的网络库,更容易让初学者快速掌握

什么是 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. 
 * 

* Values of the map on which this annotation exists will be processed in one of two ways: *

    *
  • If the type is {@link okhttp3.RequestBody RequestBody} the value will be used * directly with its content type.
  • *
  • Other object types will be converted to an appropriate representation by using * {@linkplain Converter a converter}.
  • *
*

*

 
 * @Multipart 
 * @POST("/upload") 
 * Call upload( 
 * @Part("file") RequestBody file, 
 * @PartMap Map params); 
 * 
*

* 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 upLoadAgree(@PartMap Mapparams); 
} 

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 params = new HashMap(); 
 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   泛型参数 
 */ 
 public static  void addToEnqueue(Call call, final RetrofitCallBack retrofitCallBack, final int method) { 
 final Context cOntext= MyApplication.getContext(); 
 call.enqueue(new Callback() { 
  @Override 
  public void onResponse(Call call, Response 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 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 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 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实现多图片/文件、图文上传功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!


推荐阅读
  • 解决微信电脑版无法刷朋友圈问题:使用安卓远程投屏方案
    在工作期间想要浏览微信和朋友圈却不太方便?虽然微信电脑版目前不支持直接刷朋友圈,但通过远程投屏技术,可以轻松实现在电脑上操作安卓设备的功能。 ... [详细]
  • 本文总结了在使用Ionic 5进行Android平台APK打包时遇到的问题,特别是针对QRScanner插件的改造。通过详细分析和提供具体的解决方法,帮助开发者顺利打包并优化应用性能。 ... [详细]
  • QUIC协议:快速UDP互联网连接
    QUIC(Quick UDP Internet Connections)是谷歌开发的一种旨在提高网络性能和安全性的传输层协议。它基于UDP,并结合了TLS级别的安全性,提供了更高效、更可靠的互联网通信方式。 ... [详细]
  • 本文基于对相关论文和开源代码的研究,详细介绍了LOAM(激光雷达里程计与建图)的工作原理,并对其关键技术进行了分析。 ... [详细]
  • 本文详细记录了在基于Debian的Deepin 20操作系统上安装MySQL 5.7的具体步骤,包括软件包的选择、依赖项的处理及远程访问权限的配置。 ... [详细]
  • 资源推荐 | TensorFlow官方中文教程助力英语非母语者学习
    来源:机器之心。本文详细介绍了TensorFlow官方提供的中文版教程和指南,帮助开发者更好地理解和应用这一强大的开源机器学习平台。 ... [详细]
  • 探讨如何高效使用FastJSON进行JSON数据解析,特别是从复杂嵌套结构中提取特定字段值的方法。 ... [详细]
  • 构建基于BERT的中文NL2SQL模型:一个简明的基准
    本文探讨了将自然语言转换为SQL语句(NL2SQL)的任务,这是人工智能领域中一项非常实用的研究方向。文章介绍了笔者在公司举办的首届中文NL2SQL挑战赛中的实践,该比赛提供了金融和通用领域的表格数据,并标注了对应的自然语言与SQL语句对,旨在训练准确的NL2SQL模型。 ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • This document outlines the recommended naming conventions for HTML attributes in Fast Components, focusing on readability and consistency with existing standards. ... [详细]
  • 在现代网络环境中,两台计算机之间的文件传输需求日益增长。传统的FTP和SSH方式虽然有效,但其配置复杂、步骤繁琐,难以满足快速且安全的传输需求。本文将介绍一种基于Go语言开发的新一代文件传输工具——Croc,它不仅简化了操作流程,还提供了强大的加密和跨平台支持。 ... [详细]
  • 从零开始构建完整手机站:Vue CLI 3 实战指南(第一部分)
    本系列教程将引导您使用 Vue CLI 3 构建一个功能齐全的移动应用。我们将深入探讨项目中涉及的每一个知识点,并确保这些内容与实际工作中的需求紧密结合。 ... [详细]
  • 本报告涵盖了个人博客账号和码云账号的注册过程,以及对网络工程专业学习的反思与展望。通过回顾初入大学时的专业选择,分析当前的专业知识和技能水平,并对未来的职业规划进行了详细讨论。 ... [详细]
  • 本文详细记录了在银河麒麟操作系统和龙芯架构上使用 Qt 5.15.2 进行项目打包时遇到的问题及解决方案,特别关注于 linuxdeployqt 工具的应用。 ... [详细]
  • VSCode与Gitee集成:项目提交的高效实践
    本文介绍如何利用VSCode内置的Git工具将项目提交到Gitee,简化Git命令的使用,提升代码管理效率。同时分享一些常见的踩坑经验和解决方案。 ... [详细]
author-avatar
惰堂_301
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有