Retrofit's file upload and progress alerts

1. Write an interface for upload monitoring:

/**
 * Created by Zzm丶Fiona on 2017/7/31.
 */

public interface RetrofitProgressUploadListener {
    /**
     *
     * @param bytesWriting the number of bytes written
     * @param totalBytes The total bytes of the file
     */
    void onProgress(long bytesWriting, long totalBytes);
}

2. Rewrite a class to inherit from RequestBody:

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();
    }

    // key method
    @Override
    public void writeTo(BufferedSink sink) throws IOException {
        if (null == bufferedSink) bufferedSink = Okio.buffer(sink(sink));
        requestBody.writeTo(bufferedSink);
        //must call flush, otherwise the last part of the data may not be written
        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;
                       //Call the interface to pass the progress of uploading the file to the past
                retrofitProgressUploadListener.onProgress(bytesWriting, contentLength);
            }
        };
    }
}

3. The encapsulated method returns 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 transfers the data to the main thread for processing, display
    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. Inherit your own class from ProgressRequestBody of RequesBody and pass it into the uploaded form:

/**
 * 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"),your upload file-file);
        ProgressRequestBody progressRequestBody = RetrofitUploadProgressUtil.getProgressRequesBody(requestBody, new Handler() {
            @Override
            public void handleMessage(Message msg) {
          //Display of progress:
                super.handleMessage(msg);
                Log.i("zzmzzm", "Bytes read: " + ((UploadProgressBean) msg.obj).getTotalBytes());
                Log.i("zzmzzm", "Total bytes of uploaded files: " + ((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) {
//return on successful intercession
                try {
                    Log.i("zzmzzm", response.body().string());
                } catch (IOException e) {
                    Log.i("zzmzzm", e.toString());
                }
            }
//return on failed intercession
            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Log.i("zzmzzm", t.toString());
            }
        });

    }

    private UploadThingsByRetrofitInterface getUploadThingsInterface() {
        return new Retrofit.Builder()
                .baseUrl("Address")
                .build()
                .create(UploadThingsByRetrofitInterface.class);
    }
}

The annotation interface among them:

/**
 * Created by Zzm丶Fiona on 2017/7/30.
 */

public interface UploadThingsByRetrofitInterface {
    @Multipart
    @POST
    Call<ResponseBody> uploadThings(@Part MultipartBody.Part uplodThings);

}

Additional instructions:

The common parameters of contentType in MediaType.parse(String contentType) are:
        text / html: HTML format
        text/plain : plain text format
        text/xml : XML format
        text/x-markdown: markdown documents
        image/gif : gif image format
        image/jpeg: jpg image format
        image/png: png image format

        Media format types starting with application:
        application/xhtml+xml : XHTML format
        application/xml : XML data format
        application/atom+xml : Atom XML aggregation format
        application/json : JSON data format
        application/pdf : pdf format
        application/msword : Word document format
        application/octet-stream : binary stream data (like common file downloads)
        application/x-www-form-urlencoded : The default encType in <form encType=””>, the form data is encoded in key/value format and sent to the server (the default form submission data format)

        Another common media format is used when uploading files:
        multipart/form-data : This format is required when files need to be uploaded in a form

        In addition, you can refer to: http://www.w3school.com.cn/media/media_mimeref.asp

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325649515&siteId=291194637