一、关于图片上传
以前接触过的图片上传,没有使用框架,是直接通过接口跟服务器交互的状态,先将图片转成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;
}
}
};