所有代码亲测可用,如有问题,欢迎指正。
首先在ApiService接口文件中新建文件上传接口
public interface ApiService {static final String BASE_URL=" http://192.168.3.102:8080/";/*** 上传多头像*/@Multipart@POST("wzly/uploadImg") Observable<String> uploadMemberIcon(@Part List<MultipartBody.Part> partList); }
我使用ServiceFactory.java封装了Retrofit2和OkHttp
package com.wzly.iscan.tools.api;import android.util.Log;import com.google.gson.Gson;import com.google.gson.GsonBuilder;import java.io.IOException;import java.lang.reflect.Field;import java.util.Locale;import java.util.concurrent.TimeUnit;import okhttp3.FormBody;import okhttp3.Interceptor;import okhttp3.MultipartBody;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.Response;import retrofit2.Retrofit;import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;import retrofit2.converter.gson.GsonConverterFactory;/*** Created by admin on /11/15.* 单例模式:每次实例化出来的都是统一个实例。*/public class ServiceFactory {private final Gson mGsonDateFormat;public ServiceFactory() {mGsonDateFormat = new GsonBuilder().setDateFormat("yyyy-MM-dd hh:mm:ss").create();}private static class SingletonHolder {private static final ServiceFactory INSTANCE = new ServiceFactory();}public static ServiceFactory getInstance() {return SingletonHolder.INSTANCE;}/*** create a service** @param serviceClass* @param <S>* @return*/public <S> S createService(Class<S> serviceClass) {String baseUrl = "";try {Field field1 = serviceClass.getField("BASE_URL");baseUrl = (String) field1.get(serviceClass);} catch (NoSuchFieldException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.getMessage();e.printStackTrace();}Retrofit retrofit = new Retrofit.Builder().baseUrl(baseUrl).client(getOkHttpClient()).addConverterFactory(GsonConverterFactory.create(mGsonDateFormat)).addCallAdapterFactory(RxJavaCallAdapterFactory.create()).build();return retrofit.create(serviceClass);}private final static long DEFAULT_TIMEOUT = 10;private OkHttpClient getOkHttpClient() {//定制OkHttpOkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();//设置超时时间 httpClientBuilder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);httpClientBuilder.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);httpClientBuilder.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);httpClientBuilder.addInterceptor(new RequestInterceptor());httpClientBuilder.addInterceptor(new LogInterceptor());return httpClientBuilder.build();}/*** 日志拦截器*/private class LogInterceptor implements Interceptor {@Overridepublic okhttp3.Response intercept(Chain chain) throws IOException {long t1 = System.nanoTime();okhttp3.Response response = chain.proceed(chain.request());long t2 = System.nanoTime();Log.v("zcb", String.format(Locale.getDefault(), "Received response for %s in %.1fms%n%s",response.request().url(), (t2 - t1) / 1e6d, response.headers()));okhttp3.MediaType mediaType1 = response.body().contentType();String content = response.body().string();Log.i("zcb", "response body:" + content);return response.newBuilder().body(okhttp3.ResponseBody.create(mediaType1, content)).build();}}/*** 请求拦截器,修改请求header*/private class RequestInterceptor implements Interceptor{@Overridepublic Response intercept(Chain chain) throws IOException {Request request = chain.request().newBuilder().build();Log.v("zcb", "request:" + request.toString());Log.v("zcb", "request headers:" + request.headers().toString());return chain.proceed(request);}}}
View Code
此外也用HttpResultSubscriber.java封装了Subscriber,代码如下:
package com.wzly.iscan.tools.api;import retrofit2.adapter.rxjava.HttpException;import rx.Subscriber;/*** Created by zcb* Date:/7/27* Time:21:27*/public abstract class HttpResultSubscriber<T> extends Subscriber<T> {@Overridepublic void onCompleted() {}@Overridepublic void onNext(T t) {onSuccess(t);}@Overridepublic void onError(Throwable e) {e.printStackTrace();//在这里做全局的错误处理if (e instanceof HttpException) {// ToastUtils.getInstance().showToast(e.getMessage()); }_onError(e);}public abstract void onSuccess(T t);public abstract void _onError(Throwable e);}
View Code
接下来是多文件上传的关键代码:
public void uploadAvatarImg(String urlpath,String fileName,String sign) {List<String> imgList=new ArrayList<String>();imgList.add(urlpath);MultipartBody.Builder builder=new MultipartBody.Builder().setType(MultipartBody.FORM) //表单类型.addFormDataPart("imgfile","avatar.jpg").addFormDataPart("sign",APPConfig.serverSign);//多张图for (int i=0;i<imgList.size();i++){File file=new File(imgList.get(i));RequestBody requestBody=RequestBody.create(MediaType.parse("multipart/form-data"),file);builder.addFormDataPart("imgfile"+i,file.getName(),requestBody);//"imgfile"+i 后台接收图片流的参数名 }List<MultipartBody.Part> parts=builder.build().parts();Observable observable=ServiceFactory.getInstance().createService(ApiService.class).uploadMemberIcon(parts);observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new HttpResultSubscriber<UploadImgResult>() {@Overridepublic void onSuccess(UploadImgResult uploadImgResult) {int error_code=uploadImgResult.error_code;String msg=uploadImgResult.msg;String path=uploadImgResult.imgPath;Log.i("zcb","code:"+error_code+"msg:"+msg+"path:"+path);registerView.onUploadAvatarImgResult(msg,error_code,path);}@Overridepublic void _onError(Throwable e) {}});}
View Code
最后是后台服务器端测试文件上传用的servlet代码UploadImg.java,
服务端环境tomcat8.5 jdk1.8
查看代码
package wzly;import java.io.File;import java.io.IOException;import java.util.Date;import java.util.Iterator;import java.util.List;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import mons.fileupload.DiskFileUpload;import mons.fileupload.FileItem;import org.json.JSONException;import org.json.JSONObject;/*** Servlet implementation class UploadImg*/@WebServlet("/UploadImg")public class UploadImg extends HttpServlet {private static final long serialVersionUID = 1L;public UploadImg() { }private String fileName="";private boolean success=false;protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// TODO Auto-generated method stubresponse.getWriter().append("you are using get method Served at: ").append(request.getContextPath());}//服务器servlet代码protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("开始接受文件");String temp=request.getSession().getServletContext().getRealPath("/")+"temp"; //临时目录System.out.println("temp="+temp);String loadpath=request.getSession().getServletContext().getRealPath("/")+"Image"; //上传文件存放目录System.out.println("loadpath="+loadpath);DiskFileUpload fu =new DiskFileUpload();fu.setSizeMax(5*1024*1024); // 设置允许用户上传文件大小,单位:字节fu.setSizeThreshold(4096); // 设置最多只允许在内存中存储的数据,单位:字节fu.setRepositoryPath(temp); // 设置一旦文件大小超过getSizeThreshold()的值时数据存放在硬盘的目录//开始读取上传信息int index=0;List fileItems =null;try {fileItems = fu.parseRequest(request);System.out.println("fileItems="+fileItems);} catch (Exception e) {e.printStackTrace();}Iterator iter = fileItems.iterator(); // 依次处理每个上传的文件while (iter.hasNext()){FileItem item = (FileItem)iter.next();// 忽略其他不是文件域的所有表单信息if (!item.isFormField()){fileName = item.getName();//获取上传文件名,包括路径fileName=fileName.substring(fileName.lastIndexOf("\\")+1);//从全路径中提取文件名long size = item.getSize();if((fileName==null||fileName.equals("")) && size==0)continue;int point = fileName.indexOf(".");fileName=(new Date()).getTime()+fileName.substring(point,fileName.length());index++;File fNew=new File(loadpath, fileName);try {item.write(fNew);success=true;} catch (Exception e) {// TODO Auto-generated catch blocksuccess=false;e.printStackTrace();}}else//取出不是文件域的所有表单信息{ String fieldName=item.getFieldName();String fieldvalue = item.getString();//如果包含中文应写为:(转为UTF-8编码) System.out.println(fieldName);System.out.println(fieldvalue);// String fieldvalue = new String(item.getString().getBytes(),"UTF-8"); }}JSONObject json=new JSONObject();try {if(success){String imgPath="image/"+fileName.substring(0, fileName.length());json.put("error_code", 1);json.put("msg", "upload success");json.put("imgPath", imgPath);}else{json.put("error_code", 0);json.put("msg", "upload fail");json.put("imgPath", "");}} catch (JSONException e) {e.printStackTrace();}response.getWriter().append(json.toString());//response.sendRedirect("result.jsp?imgPath="+ json.toString()); }}