OKHttp3学习之九:文件上传(拦截器获取上传进度)

通过重写请求进行文件上传拦截,实现进度计算。

包装请求体,处理进度

public class ProgressRequestBody extends RequestBody {

    //实际的待包装请求体
    private final RequestBody requestBody;
    //进度回调接口
    private final ProgressListener progressListener;
    //包装完成的BufferedSink
    private BufferedSink bufferedSink;

    public ProgressRequestBody(RequestBody requestBody, ProgressListener progressListener) {
        this.requestBody = requestBody;
        this.progressListener = progressListener;
    }

    @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 (bufferedSink == null) {
            bufferedSink = Okio.buffer(getSink(sink));
        }
        //写入
        requestBody.writeTo(bufferedSink);
        //必须调用flush,否则最后一部分数据可能不会被写入
        bufferedSink.flush();
    }

    private Sink getSink(Sink sink) throws IOException {
        return new ForwardingSink(sink) {
            long contentLength = contentLength();
            long writeLength = 0;

            @Override
            public void write(Buffer source, long byteCount) throws IOException {
                super.write(source, byteCount);
                //Log.i("yezhou", "ProgressRequestBody: writeLength=" + writeLength + ", byteCount=" + byteCount);
                if (writeLength < contentLength) {
                    writeLength += byteCount;
                    int progress = (int) (writeLength * 1.0f / contentLength * 100);
                    progressListener.onProgress(progress);
                } else {
                    progressListener.onDone(contentLength);
                }
            }
        };
    }
}

封装上传进度拦截器

public void uploadFileWithInterceptors(View view) {
    OkHttpClient client = new OkHttpClient.Builder().addNetworkInterceptor(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request originRequest = chain.request();
            Request targetRequest = originRequest.newBuilder()
                    .post(new ProgressRequestBody(originRequest.body(), new MyProgressListener()))  //封装上传进度拦截器
                    .build();
            return chain.proceed(targetRequest);
        }
    }).build();

    String uploadUrl = SERVER_ADDRESS + "/upload";
    String filePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "generated.apk";
    File file = new File(filePath);

    RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);

    RequestBody requestBody = new MultipartBody.Builder()
            .setType(MultipartBody.FORM)
            .addFormDataPart("username", "AndroidiOS.cc")  //Form表单参数
            .addFormDataPart("file", "AndroidiOS.apk", fileBody)  //文件参数
            .build();

    Request request = new Request.Builder().url(uploadUrl).post(requestBody).build();
    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            Log.i(TAG, "请求失败: " + e.getLocalizedMessage());
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            if (response.isSuccessful()) {
                Log.i(TAG, "请求成功");
            }
        }
    });
}
上一篇 OKHttp3学习之八:带参数文件上传
下一篇 Retrofit2学习之一:HelloWorld
目录
文章列表
1 Android NDK基础23:C++_类型转换_IO流_对象持久化
Android NDK基础23:C++_类型转换_IO流_对象持久化
2
Spring Security Bigcommerce OAuth2 调试记录
Spring Security Bigcommerce OAuth2 调试记录
3
Kubernetes api微服务开发之jupyter模型创建
Kubernetes api微服务开发之jupyter模型创建
4
Linux下为用户创建SSH连接
Linux下为用户创建SSH连接
5
PHP安装igbinary和redis扩展
PHP安装igbinary和redis扩展
最新评论
一位WordPress评论者
一位WordPress评论者
2月12日
您好,这是一条评论。若需要审核、编辑或删除评论,请访问仪表盘的评论界面。评论者头像来自 Gravatar。