美文网首页程序员Android知识Android技术知识
OkHttp文件上传(1):实现文件上传进度监听

OkHttp文件上传(1):实现文件上传进度监听

作者: 08_carmelo | 来源:发表于2018-01-19 22:00 被阅读0次

    前言

    OkHttp已经支持标准表单形式上传文件,具体方法参考OkHttp相关教程,本文实现文件上传的进度监听。

    原理

    关键点是自定义 支持进度反馈的RequestBody:
    重写write方法按照自定义的SEGMENT_SIZE 来写文件,从而监听进度。

    public class FileProgressRequestBody extends RequestBody {
    
        public interface ProgressListener {
            void transferred( long size );
        }
    
        public static final int SEGMENT_SIZE = 2*1024; // okio.Segment.SIZE
    
        protected File file;
        protected ProgressListener listener;
        protected String contentType;
    
        public FileProgressRequestBody(File file, String contentType, ProgressListener listener) {
            this.file = file;
            this.contentType = contentType;
            this.listener = listener;
        }
    
        protected FileProgressRequestBody() {}
    
        @Override
        public long contentLength() {
            return file.length();
        }
    
        @Override
        public MediaType contentType() {
            return MediaType.parse(contentType);
        }
    
        @Override
        public void writeTo(BufferedSink sink) throws IOException {
            Source source = null;
            try {
                source = Okio.source(file);
                long total = 0;
                long read;
    
                while ((read = source.read(sink.buffer(), SEGMENT_SIZE)) != -1) {
                    total += read;
                    sink.flush();
                    this.listener.transferred(total);
    
                }
            } finally {
                Util.closeQuietly(source);
            }
        }
    
    }
    

    FileProgressRequestBody 以2KB为单位上传,对外暴露回调ProgressListener来发布进度。接着写一个上传管理类:HttpUploader,先构造Request对象:

        protected Request generateRequest(String url){
    
            // 构造上传请求,模拟表单提交文件
            String formData = String.format("form-data;name=file; filename=%s", FileUtil.pickFileNameFromPath(fileInfo.filePath) );
            FileProgressRequestBody filePart = new FileProgressRequestBody( new File(fileInfo.filePath) , "application/octet-stream" , this );
            MultipartBody requestBody = new MultipartBody.Builder()
                    .setType(MultipartBody.FORM)
                    .addPart( Headers.of("Content-Disposition",formData), filePart )
                    .build();
    
            // 创建Request对象
            Request request = new Request.Builder()
                    .url(url)
                    .post(requestBody)
                    .build();
    
            return request;
        }
    

    传入文件路径,formData是与服务端的header约定,此处约定:name是文件名称
    定义文件上传的执行方法doUpload:

        protected int doUpload(String url){
            try {
                OkHttpClient httpClient = OkHttpClientMgr.Instance().getOkHttpClient();
                call = httpClient.newCall( generateRequest(url) );
                Response response = call.execute();
                if (response.isSuccessful()) {
                    sbFileUUID = new StringBuilder();
                    return readResponse(response,sbFileUUID);
                } else( ... ) { // 重试
                    return STATUS_RETRY;
                }
            } catch (IOException ioe) {
                LogUtil.e(LOG_TAG, "exception occurs while uploading file!",ioe);
            }
            return isCancelled() ? STATUS_CANCEL : STATUS_FAILED_EXIT;
        }
    

    上半部分是OkHttp请求的标准写法,然后对上传结果进行分析,和服务端约定返回结果。
    里面的readResponse()方法就是每次上传后读取服务端的结果:
    上传成功,可以让服务端返回文件的uuid,从response.body() 读取uuid
    上传失败,和服务端约定一个状态码,比如500执行重试。

    相关文章

      网友评论

        本文标题:OkHttp文件上传(1):实现文件上传进度监听

        本文链接:https://www.haomeiwen.com/subject/mmiaoxtx.html