1.寫一個上傳監聽的接口:html
/**
* Created by Zzm丶Fiona on 2017/7/31.
*/
public interface RetrofitProgressUploadListener {
/**
*
* @param bytesWriting 已經寫的字節數
* @param totalBytes 文件的總字節數
*/
void onProgress(long bytesWriting, long totalBytes);
}
2.從新寫一個類繼承於RequesBody:java
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:android
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傳進上傳的表單中便可:json
/** * 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); }
補充說明:markdown
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