Android OkHttp 上传文件进度指南

在Android开发中,经常需要实现文件上传功能,并且在上传的过程中提供进度更新给用户。在这篇文章中,我们将教会你如何使用OkHttp库来实现文件上传并监控进度。

流程概述

我们可以将文件上传的过程分为以下几个步骤:

步骤 描述 代码示例
1 添加OkHttp依赖 implementation 'com.squareup.okhttp3:okhttp:4.x.x'
2 创建OkHttpClient实例 OkHttpClient client = new OkHttpClient();
3 创建MultipartBody RequestBody requestBody = new MultipartBody.Builder()...
4 自定义进度回调 new UploadProgressRequestBody(...)
5 构建请求并执行 Call call = client.newCall(request);
6 处理响应 call.enqueue(new Callback() {...}

以下是整个项目的时间线甘特图展示:

gantt
    title Android OkHttp 上传文件进度 实现步骤
    dateFormat  YYYY-MM-DD
    section 步骤
    添加OkHttp依赖          :a1, 2023-10-01, 1d
    创建OkHttpClient实例    :after a1  , 1d
    创建MultipartBody       :after a1  , 1d
    自定义进度回调         :after a1  , 1d
    构建请求并执行         :after a1  , 1d
    处理响应               :after a1  , 1d

实现步骤详解

1. 添加OkHttp依赖

build.gradle文件中添加OkHttp依赖项,用于网络请求。请确保使用最新版本。

implementation 'com.squareup.okhttp3:okhttp:4.x.x' // 添加OkHttp依赖

2. 创建OkHttpClient实例

创建OkHttpClient实例,它将用于发起请求。

OkHttpClient client = new OkHttpClient(); // 创建OkHttpClient实例

3. 创建MultipartBody

使用MultipartBody来将文件以及其他参数打包为一个请求体。

File file = new File("path/to/your/file.txt"); // 本地文件路径
RequestBody fileBody = RequestBody.create(MediaType.parse("text/plain"), file); // 创建文件请求体

// 创建MultipartBody
RequestBody requestBody = new MultipartBody.Builder()
        .setType(MultipartBody.FORM) // 设置表单类型
        .addFormDataPart("file", file.getName(), fileBody) // 添加文件
        .build();

4. 自定义进度回调

通过扩展RequestBody,我们可以实现一个自定义的上传进度回调。

class UploadProgressRequestBody extends RequestBody {
    private final RequestBody requestBody;
    private final ProgressListener listener;

    public interface ProgressListener {
        void onProgress(long totalBytes, long bytesWritten);
    }

    public UploadProgressRequestBody(RequestBody requestBody, ProgressListener listener) {
        this.requestBody = requestBody;
        this.listener = listener;
    }

    @Override
    public MediaType contentType() {
        return requestBody.contentType();
    }

    @Override
    public void writeTo(BufferedSink sink) throws IOException {
        CountingSink countingSink = new CountingSink(sink);
        BufferedSink bufferedSink = Okio.buffer(countingSink);
        requestBody.writeTo(bufferedSink);
        bufferedSink.flush();
    }

    private final class CountingSink extends ForwardingSink {
        private long bytesWritten = 0;
        private long contentLength = 0;

        CountingSink(Sink delegate) {
            super(delegate);
        }

        @Override
        public void write(Buffer source, long byteCount) throws IOException {
            super.write(source, byteCount);
            bytesWritten += byteCount;
            if (contentLength == 0) {
                contentLength = requestBody.contentLength();
            }
            listener.onProgress(contentLength, bytesWritten); // 更新进度
        }
    }
}

5. 构建请求并执行

在创建完请求体后,我们可以构建请求并执行。

UploadProgressRequestBody uploadProgressRequestBody = new UploadProgressRequestBody(requestBody, 
    (totalBytes, bytesWritten) -> {
        // 在这里可以更新UI或日志
        float progress = (float) bytesWritten / totalBytes * 100;
        Log.d("Upload Progress", progress + "%");
    });

Request request = new Request.Builder()
        .url(" // 上传API地址
        .post(uploadProgressRequestBody) // 使用自定义请求体
        .build();

client.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        e.printStackTrace(); // 上传失败处理
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        if (response.isSuccessful()) {
            // 成功后处理逻辑
        }
    }
});

6. 处理响应

在上传完毕后,你可能需要处理服务器响应,比如判断上传是否成功。

结尾

通过以上步骤,你应该已经掌握了如何使用OkHttp实现Android文件上传并提供上传进度反馈。这种实现方式不仅有效提升了用户体验,还能够处理网络异常和响应。如果你有更多问题,希望你能继续探索OkHttp的其他功能,提升你的开发技能。

同时,为了更好地理解这个过程,你可以参考如下的饼状图,展示了各步骤在整个实现过程中的时间分配:

pie
    title 实现步骤时间分配
    "添加OkHttp依赖": 10
    "创建OkHttpClient实例": 15
    "创建MultipartBody": 20
    "自定义进度回调": 25
    "构建请求并执行": 20
    "处理响应": 10

希望这篇文章能对你有所帮助,祝你在Android开发的道路上,一帆风顺!