Rxjava+Retrofit2+Okhttp3多文件上传(服务器端代码+客户端代码)

所有代码亲测可用,如有问题,欢迎指正。

 

首先在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 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 <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() {
        //定制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);
        }
    }

}
View Code

此外也用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 HttpResultSubscriber<T> extends Subscriber<T> {
    


    @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);
}
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>() {
                    @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) {

                    }
                });
    }
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 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());
        }
    

}
posted @ 2016-12-27 10:53  客舍青  阅读(1388)  评论(0编辑  收藏  举报