Retrofit的文件上傳和進度提示

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
相關文章
相關標籤/搜索