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, "请求成功");
            }
        }
    });
}

版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/02/25/okhttp3-learning-9-file-upload-interceptor-to-obtain-upload-progress/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
海报
OKHttp3学习之九:文件上传(拦截器获取上传进度)
通过重写请求进行文件上传拦截,实现进度计算。 包装请求体,处理进度 public class ProgressRequestBody extends RequestBody { //实际的待包装请求体 ……
<<上一篇
下一篇>>
文章目录
关闭
目 录