zoukankan      html  css  js  c++  java
  • Retrofit的文件上传和进度提示

    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

  • 相关阅读:
    一起学习Avalonia(八)
    国产下的netcore
    一起学习Avalonia(七)
    一起学习Avalonia(六)
    一起学习Avalonia补充(deepin下的使用开发t调试)
    一起学习Avalonia(五)
    一起学习Avalonia补充(Linux下的使用开发)
    一起学习Avalonia(四)
    一起学习Avalonia(三)
    html页面边框的简单设置方法
  • 原文地址:https://www.cnblogs.com/twodog/p/12139836.html
Copyright © 2011-2022 走看看