android okhttp 文件上传如何获取上传进度
  Scjmn2WXb8Ak 2023年12月23日 11 0

Android OkHttp 文件上传如何获取上传进度

在Android开发中,使用OkHttp库进行文件上传是一种常见的方式。然而,当上传大文件时,我们通常希望能够获取上传进度以提供更好的用户体验。本文将介绍如何使用OkHttp来实现文件上传并获取上传进度。

实际问题

在实际开发中,我们可能需要上传用户拍摄的照片或者录制的视频等大文件。由于文件较大,上传过程可能需要一段时间。为了提供更好的用户体验,我们希望能够显示上传进度,让用户清楚地知道上传的进展情况。

解决方案

为了获取上传进度,我们需要使用OkHttp的RequestBody和Interceptor。

1. 添加依赖

首先,在项目的build.gradle文件中添加OkHttp的依赖:

dependencies {
    implementation 'com.squareup.okhttp3:okhttp:4.9.0'
}

2. 创建上传任务

我们可以创建一个UploadTask类来封装文件上传的逻辑。在该类中,我们需要定义一个接口来回调上传进度:

public class UploadTask {
    private static final String TAG = "UploadTask";

    public interface ProgressListener {
        void onProgress(long bytesWritten, long contentLength, boolean done);
    }

    public void uploadFile(File file, ProgressListener listener) {
        OkHttpClient client = new OkHttpClient().newBuilder()
                .addInterceptor(new ProgressInterceptor(listener))
                .build();

        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("file", file.getName(),
                        RequestBody.create(MediaType.parse("multipart/form-data"), file))
                .build();

        Request request = new Request.Builder()
                .url("http://your-upload-url")
                .post(requestBody)
                .build();

        try {
            Response response = client.newCall(request).execute();
            // 处理上传结果
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在uploadFile方法中,我们创建了一个OkHttpClient实例,并添加了一个Interceptor(ProgressInterceptor)来监听上传进度。然后,我们构建了一个MultipartBody,将文件添加为表单数据,并发送POST请求。

注意:在示例代码中的URL处应该替换为你自己的上传接口地址。

3. 实现进度监听器

我们需要自定义一个Interceptor来监听上传进度,并通过回调函数通知上传进度的变化。下面是ProgressInterceptor的实现:

public class ProgressInterceptor implements Interceptor {
    private static final String TAG = "ProgressInterceptor";

    private UploadTask.ProgressListener mListener;

    public ProgressInterceptor(UploadTask.ProgressListener listener) {
        mListener = listener;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request originalRequest = chain.request();
        Response originalResponse = chain.proceed(originalRequest);

        return originalResponse.newBuilder()
                .body(new ProgressResponseBody(originalResponse.body(), mListener))
                .build();
    }

    private static class ProgressResponseBody extends ResponseBody {
        private final ResponseBody mResponseBody;
        private final UploadTask.ProgressListener mListener;
        private BufferedSource mBufferedSource;

        public ProgressResponseBody(ResponseBody responseBody, UploadTask.ProgressListener listener) {
            mResponseBody = responseBody;
            mListener = listener;
        }

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

        @Override
        public long contentLength() {
            return mResponseBody.contentLength();
        }

        @Override
        public BufferedSource source() {
            if (mBufferedSource == null) {
                mBufferedSource = Okio.buffer(source(mResponseBody.source()));
            }
            return mBufferedSource;
        }

        private Source source(Source source) {
            return new ForwardingSource(source) {
                long totalBytesRead = 0L;

                @Override
                public long read(Buffer sink, long byteCount) throws IOException {
                    long bytesRead = super.read(sink, byteCount);
                    totalBytesRead += bytesRead != -1 ? bytesRead : 0;
                    if (mListener != null) {
                        mListener.onProgress(totalBytesRead, mResponseBody.contentLength(), bytesRead == -1);
                    }
                    return bytesRead;
                }
            };
        }
    }
}

在ProgressInterceptor中,我们通过调用chain.proceed(originalRequest)来获取原始的Response对象。然后,我们构建一个新的Response对象,将原始的ResponseBody替换为自定义的ProgressResponseBody。ProgressResponseBody会在读取数据时回调进度监听器。

4. 使用示例

使用UploadTask来上传文件并监听上传进度的示例如下:

public class MainActivity extends AppCompatActivity {
    private static final String
【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月23日 0

暂无评论

Scjmn2WXb8Ak