所有代码亲测可用,如有问题,欢迎指正。
首先在ApiService接口文件中新建文件上传接口
public interface ApiService { static final String BASE_URL=" http://192.168.3.102:8080/"; /** * 上传多头像 */ @Multipart @POST("wzly/uploadImg") ObservableuploadMemberIcon(@Part List 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 2016/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* @return */ publicS createService(ClassserviceClass) { 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() { //定制OkHttp OkHttpClient.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 { @Override public 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{ @Override public 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); } }}
此外也用HttpResultSubscriber.java封装了Subscriber,代码如下:
package com.wzly.iscan.tools.api;import retrofit2.adapter.rxjava.HttpException;import rx.Subscriber;/** * Created by zcb * Date:2016/7/27 * Time:21:27 */public abstract class HttpResultSubscriberextends Subscriber { @Override public void onCompleted() { } @Override public void onNext(T t) { onSuccess(t); } @Override public 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);}
接下来是多文件上传的关键代码:
public void uploadAvatarImg(String urlpath,String fileName,String sign) { ListimgList=new ArrayList (); 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 parts=builder.build().parts(); Observable observable=ServiceFactory.getInstance().createService(ApiService.class).uploadMemberIcon(parts); observable.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new HttpResultSubscriber () { @Override public 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); } @Override public void _onError(Throwable e) { } }); }
最后是后台服务器端测试文件上传用的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 org.apache.commons.fileupload.DiskFileUpload;import org.apache.commons.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 stub response.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 block success=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()); } }