Retrofit图片上传及进度的显示

一、关于图片上传

以前接触过的图片上传,没有使用框架,是直接通过接口跟服务器交互的状态,先将图片转成base64String,然后添加到json当中,再通过接口发送给服务器,当时单张图片还好说,如果是多张而且大小不小的话,传输就相当慢了,现在接触到的retrofit,上传文件,当然包括图片,提供了自己的方法,上传单张和多张的速度很快,效率得到了大大的提升而;

二、实现文件上传
接口的编写,是以post请求的方式提交,ImageReturnBean是服务器返回的上传结果,@Part(“userid”) String userid则是上传文件时携带的参数id, PartMap 作为存放需要上传的文件的集合;

  /**
    * 图片上传
    * @return
    */
    @Multipart
    @POST("uploadimage")
    Call uploadFiles(@Part("userid") String userid,@PartMap Map params);

接下来是图片上传的请求,UploadFileRequestBody是我们自己封装,将文件添加到RequestBody中,这里在后面解释, params.put(“test” + i + “\”; filename=\”” + file.getName(), fileRequestBody);添加文件的键以及值RequestBody,在遍历图片文件的同时生成对应的body,添加到集合中;

 Retrofit retrofit = new Retrofit.Builder()
      .baseUrl(HttpUtil.loadLoginUrl)
      .addConverterFactory(GsonConverterFactory.create())
      .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
      .build();
APIService service = retrofit.create(APIService.class);
Map params = new HashMap<>();
for (int i = 0; i < imageList.size(); i++) {
    File file = new File(imageList.get(i)); 
    UploadFileRequestBody fileRequestBody = new UploadFileRequestBody(file, new DefaultProgressListener(myHandler, 1, imageList.size()));
    params.put("test" + i + "\"; filename=\"" + file.getName(), fileRequestBody);
    }
Call observable = service.uploadFiles(resultsBean.getUserid(),params);
observable.enqueue(new Callback() {
     @Override
     public void onResponse(Response response, Retrofit retrofit) {
           progressDialog.dismiss();
           Log.e("上传成功", "" + ((ImageReturnBean) response.body()).getMsg());
        }

      @Override
      public void onFailure(Throwable t) {
           progressDialog.dismiss();
           Log.e("上传失败", "上传失败");
      }
    });
  }
});

下面我们来看看自己封装的RequestBody类

public class UploadFileRequestBody extends RequestBody {

    private RequestBody mRequestBody;
    private ProgressListener mProgressListener;
    private BufferedSink bufferedSink;

    public UploadFileRequestBody(File file, ProgressListener progressListener) {
        this.mRequestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
        this.mProgressListener = progressListener;
    }

    public UploadFileRequestBody(RequestBody requestBody, ProgressListener progressListener) {
        this.mRequestBody = requestBody;
        this.mProgressListener = progressListener;
    }

    //返回了requestBody的类型,想什么form-data/MP3/MP4/png等等等格式
    @Override
    public MediaType contentType() {
        return mRequestBody.contentType();
    }

    //返回了本RequestBody的长度,也就是上传的totalLength
    @Override
    public long contentLength() throws IOException {
        return mRequestBody.contentLength();
    }

    @Override
    public void writeTo(BufferedSink sink) throws IOException {
        if (bufferedSink == null) {
            //包装
            bufferedSink = Okio.buffer(sink(sink));
        }
        //写入
        mRequestBody.writeTo(bufferedSink);
        //必须调用flush,否则最后一部分数据可能不会被写入
        bufferedSink.flush();
    }

    private Sink sink(Sink sink) {
        return new ForwardingSink(sink) {
            //当前写入字节数
            long bytesWritten = 0L;
            //总字节长度,避免多次调用contentLength()方法
            long contentLength = 0L;

            @Override
            public void write(Buffer source, long byteCount) throws IOException {
                super.write(source, byteCount);
                if (contentLength == 0) {
                    //获得contentLength的值,后续不再调用
                    contentLength = contentLength();
                }
                //增加当前写入的字节数
                bytesWritten += byteCount;
                //回调上传接口
                mProgressListener.onProgress(bytesWritten, contentLength, bytesWritten == contentLength);
            }
        };
    }
}

给出回调的上传接口:

public interface ProgressListener {

    void onProgress(long hasWrittenLen, long totalLen, boolean hasFinish);
}

我们定义一个类实现这个监听的接口

public class DefaultProgressListener implements ProgressListener {

    private Handler mHandler;
    private int size;

    //多文件上传时,index作为上传的位置的标志
    private int mIndex;

    public DefaultProgressListener(Handler mHandler, int mIndex, int size) {
        this.mHandler = mHandler;
        this.mIndex = mIndex;
        this.size = size;
    }

    @Override
    public void onProgress(long hasWrittenLen, long totalLen, boolean hasFinish) {
        System.out.println("----the current " + hasWrittenLen + "----" + totalLen + "-----" + (hasWrittenLen * 100 / totalLen));
        int percent = (int) (hasWrittenLen * 100 / totalLen);
        if (percent > 100) percent = 100;
        if (percent < 0) percent = 0;
        if (percent == 100) {
            Constant.LASTSIZE += percent / size;
        }
        Message msg = Message.obtain();
        if ((Constant.LASTSIZE + percent / size) > 100) {
            msg.what = 100;
        } else {
            msg.what = Constant.LASTSIZE + percent / size;
        }
        msg.arg1 = mIndex;
        //这里因为有多张图片,二一开始进度只是单张的,所以根据图片的size计算总的进度;
        if (Constant.LOADSIZE < msg.what) {
            Constant.LOADSIZE = msg.what;
            mHandler.sendMessage(msg);
        }
    }
}

最后在更新界面接受消息后更新UI

private Handler myHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.arg1) {
                case 1:
                    if (msg.what > 0) {
                        Log.e("上传进度", "=" + msg.what + "%");
                        mFirstBar.setProgress(msg.what);
                        tv_progress.setText(msg.what + "%");
                    }
                    break;
            }
        }
    };

“`
Retrofit图片上传及进度的显示_第1张图片

你可能感兴趣的:(Android请求,图片文件上传,进度条,retrofit,图文上传)