rxjava,retrofit实现多图片上传

需要知道的知识

  1. 在我们写html页面进行文件上传的时候我们必须要在表单form中添加enctype="multipart/form-data"属性并在表单中使用这样的输入项,如果读者想知道其中的原理请看http协议
  2. 了解rxjava和retrofit的结合使用

实现图片上传的步骤

  1. 搭建服务端在这里我使用最简单的servlet和apache提供的文件上传下载的服务端(可自行学习,也可忽略不看)
public class UploadPic extends HttpServlet{
private static final long serialVersionUID = 1L;

    public UploadPic() {
        super();
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setCharacterEncoding("utf-8");
        try {
            // 1.进行文件上传
            DiskFileItemFactory disk = new DiskFileItemFactory();
            disk.setSizeThreshold(1024 * 1024 * 1);
            disk.setRepository(new File(this.getServletContext().getRealPath("WEB-INF/temp")));

            ServletFileUpload upload = new ServletFileUpload(disk);
            if (!ServletFileUpload.isMultipartContent(request)) {
                throw new RuntimeException("请使用正确的文件表单上传项");
            }
            upload.setFileSizeMax(1024 * 1024 * 1);
            upload.setSizeMax(1024 * 1024 * 10);
            upload.setHeaderEncoding("utf-8");
            upload.setProgressListener(new ProgressListener() {
                Long beginTime = System.currentTimeMillis();

                @Override
                public void update(long bytesRead, long contentLength, int items) {
                    try {
                        Thread.sleep(500); // 为了显示测试的效果
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    BigDecimal br = new BigDecimal(bytesRead).divide(new BigDecimal(1024), 2, BigDecimal.ROUND_HALF_UP);
                    BigDecimal cl = new BigDecimal(contentLength).divide(new BigDecimal(1024), 2,
                            BigDecimal.ROUND_HALF_UP);
                    // 剩余字节数
                    BigDecimal ll = cl.subtract(br);
                    // 上传百分比
                    BigDecimal per = br.multiply(new BigDecimal(100)).divide(cl, 2, BigDecimal.ROUND_HALF_UP);
                    // 上传用时
                    Long nowTime = System.currentTimeMillis();
                    Long useTime = (nowTime - beginTime) / 1000;
                    // 上传速度
                    BigDecimal speed = new BigDecimal(0);
                    if (useTime != 0) {
                        speed = br.divide(new BigDecimal(useTime), 2, BigDecimal.ROUND_HALF_UP);
                    }
                    // 大致剩余时间
                    BigDecimal ltime = new BigDecimal(0);
                    if (!speed.equals(new BigDecimal(0))) {
                        ltime = ll.divide(speed, 0, BigDecimal.ROUND_HALF_UP);
                    }
                }
            });
            List items = upload.parseRequest(request);

            for (FileItem item2 : items) {
                if (item2.isFormField()) {
                    // 正常的表单项
                    String name = item2.getFieldName();
                    String value = item2.getString("utf-8");
                    System.out.println(name + "====" + value);
                } else {
                    // 文件上传项
                    // 得到文件名
                    String name = item2.getName(); // 有时候是一个全路径有时候只是一个文件名
                    String[] temps = name.split("\\\\");
                    name = temps[temps.length - 1];

                    // 使得文件名唯一
                    String uuidName = UUID.randomUUID().toString() + "_" + name;

                    // 使得文件夹中只有一个文件
                    String hash = Integer.toHexString(uuidName.hashCode());
                    String path = this.getServletContext().getRealPath("WEB-INF/upload");
                    System.out.println("path==========" + path);
                    String imgUrl = "/WEB-INF/upload";
                    for (char c : hash.toCharArray()) {
                        path += "/" + c;
                        imgUrl += "/" + c;
                    }
                    imgUrl += "/" + uuidName;
                    // 文件夹不存在则进行创建
                    File f = new File(path);
                    if (!f.exists()) {
                        f.mkdirs();
                    }
                    System.out.println("file==========" + f.getPath());
                    // 进行文件的保存
                    InputStream in = item2.getInputStream();
                    OutputStream out = new FileOutputStream(new File(f, uuidName));
                    IOUtils.In2Out(in, out);
                    IOUtils.close(in, out);
                    item2.delete();
                }
            }
            System.out.println("上传成功");
            // 上传成功
            response.getWriter().write("{\"flag\":1}");

        } catch (Exception e) {
            e.printStackTrace();
            // 上传失败
            response.getWriter().write("{\"flag\":0}");
            throw new RuntimeException(e);
        }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}
  1. 实现通过app来进行图片的上传
    2.1. 导入依赖的包
    引入rxjava2
    compile 'io.reactivex.rxjava2:rxjava:2.0.4'
    //引入rxandroid
    compile \'io.reactivex.rxjava2:rxandroid:2.0.1'
    //引入retrofit
    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    //引入json转换器
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    //rxjava适配器
    compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
    

别忘了添加网络等权限哦

2.2. 创建service

   public interface ApiService {
    @Multipart   //enctype="multipart/form-data"
    @POST("UploadPic")  //图片上传的路径 使用MultipartBody.Part上
                                           传图片
    Observable uploadPic(@Part List parts);
   }

2.3. 上传图片

//Flag只是简单的标记了下上传是否成功
 private Observable upPic(){
        RetrofitClient net = RetrofitClient.getInstance(this,"上传的链接");
        ApiService service = net.create(ApiService.class);  //创建service
        List parts = new ArrayList<>();
        for (File f : files) {    //files所要上传的所有文件
            RequestBody body = RequestBody.create(MediaType.parse("image/*"),f);   //说明该文件为图片类型
//"key"相当与中的name的值 (其实没有多大的用,在后台可以遍历取出文件,一般要和后台开发人员协商的) f.getName为文件名,这两个是不一样的。

MultipartBody.Part part = MultipartBody.Part.createFormData("key", f.getName(),body);  
            parts.add(part);
        }
        return service.uploadPic(parts).compose(RetrofitClient.schedulersTransformer);
    }
    private void uploadPic(){

        Observable pics = upPic();
        pics.subscribe(new Observer() {//进行订阅

            @Override
            public void onSubscribe(Disposable d) {             }

            @Override
            public void onNext(Flag flag) {
                if (flag.getFlag()==1) {
                    Log.d("MainActivity","上传成功");
                }
            }

            @Override
            public void onError(Throwable e) {
                Log.d("MainActivity","onError===="+e.getMessage());
            }

            @Override
            public void onComplete() {
            }
        });
       }

4.效果


rxjava,retrofit实现多图片上传_第1张图片
2.png

rxjava,retrofit实现多图片上传_第2张图片
20171107163206.png

手机上没有好看的图片还请多多包涵哈!

这是eclipse上打印的

20171107163319.png

5.源码下载地址
http://pan.baidu.com/s/1hsznqBy

说明

在这个简单的项目里使用了一个图片选择器的开源项目,在源码了已经进行了标注。
RetrofitClient是我对retrofit进行了一个简单的封装,在源码中有

想要改变生活,就要先改变自己。

你可能感兴趣的:(rxjava,retrofit实现多图片上传)