Retrofit之多文件多参数上传
来源:互联网 发布:webpack 优化 编辑:程序博客网 时间:2024/05/22 13:11
Android 移动开发当中免不了要访问网络,访问网络的方式相信每个人都会有自己不同的方法,你可以自己封装网络请求,也可以用网上别人开源的框架。如果开源的框架当中,目前最受欢迎的可要数Retrofit了,而使用Retrofit中最麻烦也就是上传图片或者文件了,本文就对如何使用Retrofit同时上传多参数和多图片文件做详细的演示,并贴出相应实例代码。
在正式本文的讲解之前,先说明一下,基于现在RxJava也火得不要不要的,所以本文就结合RxJava和Retrofit一起来说明他的用法。
1.第一步:导包
现在的导包方式基本都使用Maven自动导包了,所以我们选择下面的方式而不用再去下载jar然后再导入。在Module的build.gradle文件中添加如下的依赖
compile ‘io.reactivex:rxjava:1.2.9’
compile ‘io.reactivex:rxandroid:1.2.1’
compile ‘com.squareup.retrofit2:adapter-rxjava:2.0.0’
compile ‘com.squareup.retrofit2:retrofit:2.2.0’
compile ‘com.squareup.retrofit2:converter-gson:2.2.0’
compile ‘com.squareup.okhttp3:okhttp:3.6.0’
2.第二步:构造你的Retrofit公共管理者
package com.yuanyi.logistics.manager;
import com.yuanyi.logistics.constant.Constants;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
/**
* Created by AHuan on 2017/4/24.
*/
public class RetrofitManager {
private static RetrofitManager mRetrofitManager;
private Retrofit mRetrofit;
private RetrofitManager(){ initRetrofit();}//获取同步静态对象public static synchronized RetrofitManager getInstance(){ if(mRetrofitManager==null){ mRetrofitManager=new RetrofitManager(); } return mRetrofitManager;}private void initRetrofit(){ HttpLoggingInterceptor httpLoggingInterceptor=new HttpLoggingInterceptor(); httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient.Builder builder=new OkHttpClient.Builder(); //添加过滤器 builder.addInterceptor(httpLoggingInterceptor); //设置连接超时时间 builder.connectTimeout(15, TimeUnit.SECONDS); //设置读取超时时间 builder.readTimeout(20,TimeUnit.SECONDS); //设置写超时时间 builder.writeTimeout(20,TimeUnit.SECONDS); //设置超时重连 builder.retryOnConnectionFailure(true); OkHttpClient client=builder.build(); mRetrofit=new Retrofit.Builder() .baseUrl(Constants.BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .client(client) .build();}public <T> T creatReq(Class<T> reqServer){ return mRetrofit.create(reqServer);}
}
3.编写请求接口
package com.yuanyi.logistics.network.api;
import com.yuanyi.logistics.bean.AppUpdateBean;
import com.yuanyi.logistics.bean.ResponseBean;
import com.yuanyi.logistics.bean.StorageBean;
import com.yuanyi.logistics.bean.TaskBean;
import com.yuanyi.logistics.bean.User;
import java.util.List;
import java.util.Map;
import okhttp3.RequestBody;
import retrofit2.http.Field;
import retrofit2.http.FieldMap;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.PartMap;
import retrofit2.http.Query;
import rx.Observable;
/**
* Created by AHuan on 2017/4/22.
*/
public interface TaskApi {
//获取司机的任务列表
/** * 使用post方法,查询参数声明字段是userId * @param userId * @return */@FormUrlEncoded@POST("vehicleInspectionApi/find")Observable<TaskBean> getTask(@Field("userId") String userId );//获取正在任务中的司机列表@POST("billListApi/getBydriverUserId")Observable<List<User>> getDrivers();//提交问题操作接口/** * 实现多参数post请求 * @param dataMap * @return */@FormUrlEncoded@POST("billListApi/ updateProblemGoods")Observable<ResponseBean> updateProblemGoods(@FieldMap Map<String,String> dataMap);//检测版本更新信息@POST("editionApi/editionNo")Observable<AppUpdateBean> getUpdateInfo();//获取搬仓的货物信息@FormUrlEncoded@POST("subaru_Parts/storageCarry/getByStorage")Observable<StorageBean> getStorageInfo(@Field("partNo") String partNo);//提交搬仓上传的货物信息@FormUrlEncoded@POST("subaru_Parts/storageCarry/update")Observable<ResponseBean> submitStorage(@FieldMap Map<String,String> dataMap);//上传加油数据/** * 实现多图片文件多参数上传 * @param params * @return */@Multipart@POST("vehicleInspectionApi/updateOliApi")Observable<ResponseBean> uploadAddOil(@PartMap Map<String, RequestBody> params);/** * get方法,@Query("Id")表示在Url后面追加字段是id的内容,后面的如此类推 * @param id * @param passwords * @param Pass * @return */@FormUrlEncoded@GET("userApi/updateApiPass")Observable<ResponseBean> changePw(@Query("id") int id, @Query("passwords") String passwords, @Query("Pass") String Pass);
}
4.编写工具类
编写一个专门用来生成Map的工具类。
我们以上面中的 Observable uploadAddOil();这个方法为例。
package com.yuanyi.logistics.utils;
import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import okhttp3.MediaType;
import okhttp3.RequestBody;
/**
* Created by AHuan on 2017/12/11.
* 生成Retrofit的多参数和多文件多图片的构造参数map
*/
public class RetrofitRequestBodyUtil {
/**
*使用的时候传进来的Map的构造为Map<String,Object>,如果传的是普通字符串参数的话,就往map里面put<String,String> *如果传递的是图片或者的话,就put<String,File[]>, key对应的是服务端所要的参数字段名,File[] 所对应的是上传的文件数组 * 例如服务器需要的是下面的参数 @RequestParam(value = "files") MultipartFile[] postedFiles * 我们的map中就需要put("files",File[]); * @param resourceMap * @return */public static Map<String, RequestBody> getRequestBodyMap(Map<String,Object> resourceMap){ Map<String, RequestBody> params=new HashMap<>(); Iterator iterator=resourceMap.entrySet().iterator(); while (iterator.hasNext()){ Map.Entry entry= (Map.Entry) iterator.next(); if(entry.getValue() instanceof String){ //判断值如果是String的话就直接put进去 RequestBody body=RequestBody.create(MediaType.parse("text/plain;charset=UTF-8"),(String)entry.getValue()); params.put((String)entry.getKey(),body); }else if(entry.getValue() instanceof File){ //判断当前值是单个文件的话就把key设置成服务端所要的参数子端名加文件名,具体格式可以看下面的 RequestBody body=RequestBody.create(MediaType.parse("multipart/form-data;charset=UTF-8"),(File)entry.getValue()); params.put((String)entry.getKey()+"\";filename=\""+((File)entry.getValue()).getName()+"",body); }else if(entry.getValue() instanceof File[]){ //判断当前的值是文件数组的话,要把一个个文件拆开再put进去 File[] files= (File[]) entry.getValue(); if(files!=null && files.length>0){ for(File f : files){ RequestBody body=RequestBody.create(MediaType.parse("multipart/form-data;charset=UTF-8"),f); params.put((String)entry.getKey()+"\";filename=\""+f.getName()+"",body); } } } } return params;}
}
5.下面针对上传加油数据接口贴出我的服务端代码
/**
* 添加启程
* 第一个参数为VehicleInspectionVo对象里面的属性,第二个参数是多图片文件上传
* @param vo
* @return
*/
@RequestMapping(value = "/add", method = RequestMethod.POST)public ApiResult add(VehicleInspectionVo vo, @RequestParam(value = "file") MultipartFile[] postedFiles) { ApiResult result = new ApiResult(); String fileName = "";// 返回的图片名称 用,号隔开 // 服务器路径 String path = "/upload/images/vehicleinspection/"; // 物理路径 String realPath = PathUtil.getRealPath(request, path); // 添加 fileName = fileUploaderController.imageupload(postedFiles, realPath); vo.setFileName(fileName); String msg = vehService.addApi(vo); result.setMsg(msg); if(result.getMsg().equals("录入成功")){ result.setSuccess(true); }else{ result.setSuccess(false); } return result;}
6.贴出android端的调用代码(针对上传加油数据接口实现多图片文件多参数上传)
File[] files=new File[2]; final String[] fileNames=new String[2]; for(int i=0;i<2;i++){ fileNames[i]= CreatFileUtil.createFileAndComp(imgList[i]); files[i]=new File(fileNames[i]); } final Map<String,Object> params=new HashMap<>(); params.put("id",task_id+""); params.put("oilMiles",start_km); params.put("oil",add_oil_number); params.put("gasStationAddress",address); params.put("longitude",mLongitude+""); params.put("latitude",mLatitude+""); params.put("file",files); Map<String, RequestBody> requestBodyMap = RetrofitRequestBodyUtil.getRequestBodyMap(params); showLoading("信息正在提交"); RetrofitManager.getInstance().creatReq(TaskApi.class) .uploadAddOil(requestBodyMap) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber<ResponseBean>() { @Override public void onCompleted() { closeLoading(); } @Override public void onError(Throwable e) { closeLoading(); UIUtil.show("网络出错,数据已缓存至本地"); params.remove("file"); String content=UIUtil.convertRequest(params); String filePaths=""; for(int i=0;i<fileNames.length;i++){ filePaths=filePaths+";"+fileNames[i]; } filePaths=filePaths.substring(1,filePaths.length()); UploadBean uploadBean=new UploadBean(Constants.ADD_OIL,content,filePaths); UploadRequestUtil.saveRequest(uploadBean); } @Override public void onNext(ResponseBean responseBean) { if (responseBean.success) { UIUtil.show("加油成功"); finish(); }else{ UIUtil.show(responseBean.msg); } } });
- Retrofit之多文件多参数上传
- Retrofit 2.0 单文件、多文件上传
- Android开发使用retrofit上传文件和多个参数一起时失败问题
- Retrofit 文件(图片)和参数同时上传的方法
- Retrofit 上传多张图片/文件
- Retrofit之表单提交、多文件上传
- php之多文件上传
- Retrofit 2.0文件上传
- 使用Retrofit上传文件
- Retrofit上传文件
- Retrofit 上传文件
- retrofit 上传文件
- Retrofit上传文件
- retrofit+rxjava 上传文件
- Retrofit上传文件
- Retrofit 上传文件
- AdobeFlexCookBook之多重文件上传
- 复习struts2之多文件上传
- 设计模式学习--抽象工厂模式
- 2017/12/11
- Jquery获取Select选中控件的值
- 配置struts2以及struts2需要的包
- Freemarker2.3.23使用
- Retrofit之多文件多参数上传
- Java通过JDBC进行简单的增删改查(以MySQL为例)
- nrf52832 SPi方式无操作系统与SD卡通信
- HTTP状态码
- NFS文件系统
- git常用命令及问题解决
- mycat分片
- 基于WinForms(C#)的用户登录界面(VisualStudio2013)
- C语言基础(三)