1.写一个上传监听的接口:
/**
* Created by Zzm丶Fiona on 2017/7/31.
*/
public interface RetrofitProgressUploadListener {
/**
*
* @param bytesWriting 已经写的字节数
* @param totalBytes 文件的总字节数
*/
void onProgress(long bytesWriting, long totalBytes);
}
2.重新写一个类继承于RequesBody:
package zzm.zzmotherthingsshouldknowfortheinterview.upload_progress; import android.support.annotation.Nullable; import java.io.IOException; import okhttp3.MediaType; import okhttp3.RequestBody; import okio.Buffer; import okio.BufferedSink; import okio.ForwardingSink; import okio.Okio; import okio.Sink; /** * Created by Zzm丶Fiona on 2017/7/31. */ public class ProgressRequestBody extends RequestBody { private final RetrofitProgressUploadListener retrofitProgressUploadListener; private final RequestBody requestBody; private BufferedSink bufferedSink; public ProgressRequestBody(RetrofitProgressUploadListener retrofitProgressUploadListener, RequestBody requestBody) { this.retrofitProgressUploadListener = retrofitProgressUploadListener; this.requestBody = requestBody; } @Nullable @Override public MediaType contentType() { return requestBody.contentType(); } @Override public long contentLength() throws IOException { return requestBody.contentLength(); } //关键方法 @Override public void writeTo(BufferedSink sink) throws IOException { if (null == bufferedSink) bufferedSink = Okio.buffer(sink(sink)); requestBody.writeTo(bufferedSink); //必须调用flush,否则最后一部分数据可能不会被写入 bufferedSink.flush(); } private Sink sink(Sink sink) { return new ForwardingSink(sink) { long bytesWriting = 0l; long contentLength = 0l; @Override public void write(Buffer source, long byteCount) throws IOException { super.write(source, byteCount); if (0 == contentLength) contentLength = contentLength(); bytesWriting += byteCount; //调用接口,把上传文件的进度传过去 retrofitProgressUploadListener.onProgress(bytesWriting, contentLength); } }; } }
3.封装的方法,返回ProgressRequestBody:
package zzm.zzmotherthingsshouldknowfortheinterview.utils;
import android.os.Handler;
import okhttp3.RequestBody;
import zzm.zzmotherthingsshouldknowfortheinterview.upload_progress.ProgressRequestBody;
import zzm.zzmotherthingsshouldknowfortheinterview.upload_progress.RetrofitProgressUploadListener;
import zzm.zzmotherthingsshouldknowfortheinterview.upload_progress.UploadProgressBean;
/**
* Created by Zzm丶Fiona on 2017/7/31.
*/
public class RetrofitUploadProgressUtil {
//handler把数据传送到主线程中去处理,展示
public static ProgressRequestBody getProgressRequesBody(RequestBody requestBody, final Handler handler) {
return new ProgressRequestBody(new RetrofitProgressUploadListener() {
UploadProgressBean uploadProgressBean = new UploadProgressBean();
@Override
public void onProgress(long bytesWriting, long totalBytes) {
if (null == uploadProgressBean) uploadProgressBean = new UploadProgressBean();
uploadProgressBean.setBytesWriting(bytesWriting);
uploadProgressBean.setTotalBytes(totalBytes);
handler.sendMessage(handler.obtainMessage(2, uploadProgressBean));
}
}, requestBody);
}
}
4.把自己的写的类继承于RequesBody的ProgressRequestBody传进上传的表单中即可:
/**
* Created by Zzm丶Fiona on 2017/7/30.
*/
public class UploadThingsByRetrofitActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"),你的上传文件-file);
ProgressRequestBody progressRequestBody = RetrofitUploadProgressUtil.getProgressRequesBody(requestBody, new Handler() {
@Override
public void handleMessage(Message msg) {
//进度的展示:
super.handleMessage(msg);
Log.i("zzmzzm", "已读的字节数: " + ((UploadProgressBean) msg.obj).getTotalBytes());
Log.i("zzmzzm", "上传的文件的字节总数: " + ((UploadProgressBean) msg.obj).getTotalBytes());
}
});
UploadThingsByRetrofitInterface uploadThingsByRetrofitInterface = getUploadThingsInterface();
Call<ResponseBody> upload = uploadThingsByRetrofitInterface.uploadThings(MultipartBody.Part.createFormData(你的key,文件名,progressRequestBody));
upload.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
//求情成功的返回
try {
Log.i("zzmzzm", response.body().string());
} catch (IOException e) {
Log.i("zzmzzm", e.toString());
}
}
//求情失败的返回
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.i("zzmzzm", t.toString());
}
});
}
private UploadThingsByRetrofitInterface getUploadThingsInterface() {
return new Retrofit.Builder()
.baseUrl("地址")
.build()
.create(UploadThingsByRetrofitInterface.class);
}
}
其中的注解接口:
/**
* Created by Zzm丶Fiona on 2017/7/30.
*/
public interface UploadThingsByRetrofitInterface {
@Multipart
@POST
Call<ResponseBody> uploadThings(@Part MultipartBody.Part uplodThings);
}
补充说明:
MediaType.parse(String contentType)中参数contentType常见的有:
text/html : HTML格式
text/plain :纯文本格式
text/xml : XML格式
text/x-markdown: markdown文档
image/gif :gif图片格式
image/jpeg :jpg图片格式
image/png:png图片格式
以application开头的媒体格式类型:
application/xhtml+xml :XHTML格式
application/xml : XML数据格式
application/atom+xml :Atom XML聚合格式
application/json : JSON数据格式
application/pdf :pdf格式
application/msword : Word文档格式
application/octet-stream : 二进制流数据(如常见的文件下载)
application/x-www-form-urlencoded : <form encType=””>中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)
另外一种常见的媒体格式是上传文件之时使用的:
multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式
另外的可以参考:http://www.w3school.com.cn/media/media_mimeref.asp
转载于:https://my.oschina.net/u/2987490/blog/1492353
