OkHttp获取request请求进度

对于上传文件,经常需要获得文件的上传进度反馈给用户。使用OkHttp时,可以通过包装RequestBody来实现进度反馈的功能。代码如下

<pre name="code" class="java">/**
 * OkHttp请求的进度反馈
 * 上传文件可以得到上传进度
 */
public class ProgressRequestBody extends RequestBody {

    private RequestBody requestBody;

    private ProgressListener listener;

    interface ProgressListener {
        /**
         * 请求进度回调
         *
         * @param len  已完成进度
         * @param size 总大小
         */
        void onProgress(long len, long size);
    }

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

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

    @Override
    public void writeTo(BufferedSink bufferedSink) throws IOException {
        if (listener != null) {
            // 计算总长度
            Buffer buffer = new Buffer();
            requestBody.writeTo(buffer);
            long size = buffer.size();
            if (size == -1) {
                return;
            }

            // 然后一次写2048大小的内容
            int blockSize = 2048;
            long writeSize = 0;
            while (writeSize + blockSize < size) {
                buffer.copyTo(bufferedSink.buffer(), writeSize, blockSize);
                writeSize += blockSize;
                listener.onProgress(writeSize, size);
            }
            buffer.copyTo(bufferedSink.buffer(), writeSize, size - writeSize);
            bufferedSink.flush();
            listener.onProgress(writeSize, size);
            buffer.clear();
        } else {
            requestBody.writeTo(bufferedSink);
        }
    }
}


 


使用方式上传文件中使用,注意由于ProgressListener的进度回调不在UI线程,如需刷新UI,可用Handler发送进度到主线程再刷新界面

    /**
     * 上传文件
     *
     * @param url      上传url
     * @param params   上传的其他参数
     * @param files    上传文件列表
     * @param listener 进度监听
     * @return
     * @throws IOException
     */
    public Response upload(String url, Map<String, String> params, Map<String, String> files,
                           ProgressListener listener) throws IOException {
        MultipartBuilder builder = new MultipartBuilder()
                .type(MultipartBuilder.FORM);

        //添加参数的文件
        Iterator<Entry<String, String>> paramsIterator = params.entrySet().iterator();
        while (paramsIterator.hasNext()) {
            Entry<String, String> entry = paramsIterator.next();
            String key = entry.getKey();
            String val = entry.getValue();
            builder.addFormDataPart(key, val);
        }

        //添加上传的文件
        Iterator<Entry<String, String>> filesIterator = files.entrySet().iterator();
        while (filesIterator.hasNext()) {
            Entry<String, String> entry = filesIterator.next();
            RequestBody requestBody = RequestBody
                    .create(MediaType.parse("application/octet-stream"), new File(entry.getValue()));
            builder.addFormDataPart(entry.getKey(), entry.getValue(), requestBody);
        }


        RequestBody requestBody = builder.build();

        ProgressRequestBody pdBody = new ProgressRequestBody(requestBody, listener);

        final Request request = new Request.Builder().url(url).post(pdBody).build();

        OkHttpClient client = getClient().clone();
        client.setConnectTimeout(config.uploadConnectTimeout, TimeUnit.MILLISECONDS);
        client.setReadTimeout(config.uploadReadTimeout, TimeUnit.MILLISECONDS);
        client.setWriteTimeout(config.uploadWriteTimeout, TimeUnit.MILLISECONDS);
        return client.newCall(request).execute();
    }






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android Kotlin 中使用 OkHttp3 下载文件并带有下载进度,可以通过以下步骤实现: 1. 添加 OkHttp3 依赖 在 app module 的 build.gradle 文件中添加以下代码: ``` dependencies { implementation 'com.squareup.okhttp3:okhttp:4.9.0' } ``` 2. 创建 OkHttp3 客户端 在代码中创建一个 OkHttpClient 客户端: ``` val client = OkHttpClient() ``` 3. 创建下载请求 使用 OkHttp3 的 Request.Builder 创建一个下载请求,并设置下载 URL 和保存文件的路径: ``` val request = Request.Builder() .url("https://example.com/file.zip") .build() ``` 4. 创建下载监听器 定义一个回调接口,用于监听下载进度: ``` interface DownloadListener { fun onDownloadProgress(progress: Int) } ``` 在代码中实现这个接口,并在其中更新下载进度,例如: ``` val listener = object : DownloadListener { override fun onDownloadProgress(progress: Int) { runOnUiThread { // 更新下载进度progressBar.progress = progress } } } ``` 5. 发起下载请求 使用 OkHttpClient 的 newCall 方法发起下载请求,并在 enqueue 方法中传入一个 Callback 参数,该参数将在下载完成时回调: ``` client.newCall(request).enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { // 下载失败 } override fun onResponse(call: Call, response: Response) { val inputStream: InputStream = response.body?.byteStream() ?: return // 保存文件并更新下载进度 val totalSize: Long = response.body?.contentLength() ?: -1 var downloadedSize: Long = 0 val outputStream = FileOutputStream("/storage/emulated/0/Download/file.zip") val buffer = ByteArray(8192) while (true) { val bytes = inputStream.read(buffer) if (bytes == -1) break outputStream.write(buffer, 0, bytes) downloadedSize += bytes val progress = (downloadedSize * 100 / totalSize).toInt() listener.onDownloadProgress(progress) } outputStream.close() inputStream.close() // 下载完成 } }) ``` 这段代码中,我们首先从 response.body获取输入流并创建输出流,然后使用循环逐段读取输入流的数据,再将其写入输出流,并计算下载进度,最后调用 DownloadListener 的 onDownloadProgress 方法更新下载进度。在下载完成后,我们需要关闭输入流和输出流,以及在 onFailure 方法中处理下载失败的情况。 6. 完整代码 最终的代码应该类似于这样: ``` interface DownloadListener { fun onDownloadProgress(progress: Int) } val client = OkHttpClient() val request = Request.Builder() .url("https://example.com/file.zip") .build() val listener = object : DownloadListener { override fun onDownloadProgress(progress: Int) { runOnUiThread { // 更新下载进度progressBar.progress = progress } } } client.newCall(request).enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { // 下载失败 } override fun onResponse(call: Call, response: Response) { val inputStream: InputStream = response.body?.byteStream() ?: return // 保存文件并更新下载进度 val totalSize: Long = response.body?.contentLength() ?: -1 var downloadedSize: Long = 0 val outputStream = FileOutputStream("/storage/emulated/0/Download/file.zip") val buffer = ByteArray(8192) while (true) { val bytes = inputStream.read(buffer) if (bytes == -1) break outputStream.write(buffer, 0, bytes) downloadedSize += bytes val progress = (downloadedSize * 100 / totalSize).toInt() listener.onDownloadProgress(progress) } outputStream.close() inputStream.close() // 下载完成 } }) ``` 注意,这段代码中保存文件的路径是硬编码的,你需要根据实际需求修改它。另外,为了更新 UI,我们需要在 onDownloadProgress 方法中使用 runOnUiThread 方法,以确保在主线程中执行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值