You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Ktor HTTP Client中监控请求进度?

在Kotlin多平台项目中用Ktor HTTP Client监控下载进度

嗨,我来帮你搞定这个问题!针对你使用的Ktor 1.2.5版本(CIO引擎),要给HTTP请求加上下载进度监控,有两种实用的实现方式,具体如下:

方式一:针对单个请求手动监控进度

这种方式适合只需要给特定请求添加进度监控的场景,不需要修改全局客户端配置:

// 初始化CIO客户端
val client = HttpClient(CIO)

// 发起请求并获取原始HttpResponse
val response = client.get<HttpResponse>("https://stackoverflow.com/")
// 获取响应内容总长度(可能为null,默认设为0)
val contentLength = response.contentLength() ?: 0L
var downloadedBytes = 0L

val buffer = ByteBuffer.allocate(8192) // 8KB缓冲区,可根据需求调整
val responseBodyBuilder = StringBuilder()

// 循环读取响应体字节流,同时更新进度
while (!response.content.isClosedForRead) {
    val bytesRead = response.content.readAvailable(buffer)
    if (bytesRead <= 0) break
    
    downloadedBytes += bytesRead
    // 调用你的进度更新函数
    progress(downloadedBytes, contentLength)
    
    // 将读取的字节转为字符串,拼接成最终响应体
    buffer.flip()
    responseBodyBuilder.append(Charsets.UTF_8.decode(buffer))
    buffer.clear()
}

// 最终的响应体文本
val responseBody = responseBodyBuilder.toString()

方式二:全局拦截器实现所有请求自动监控

如果你的项目中有多个请求都需要进度监控,推荐用这种全局拦截器的方式,一次配置所有请求生效:

// 初始化带有进度监控拦截器的CIO客户端
val client = HttpClient(CIO) {
    install(HttpSend) {
        intercept { request ->
            // 执行原始请求获取响应
            val originalResponse = execute(request)
            val contentLength = originalResponse.contentLength() ?: 0L
            var downloadedBytes = 0L
            
            // 包装原始响应的字节流,添加进度监控逻辑
            val monitoredContent = object : ByteReadChannel by originalResponse.content {
                override suspend fun readAvailable(dst: ByteBuffer): Int {
                    val bytesRead = originalResponse.content.readAvailable(dst)
                    if (bytesRead > 0) {
                        downloadedBytes += bytesRead
                        // 调用你的进度更新函数
                        progress(downloadedBytes, contentLength)
                    }
                    return bytesRead
                }
            }
            
            // 返回包装后的响应,后续读取响应体时会自动触发进度更新
            originalResponse.copy(content = monitoredContent)
        }
    }
}

// 正常发起请求即可,进度会自动触发
val responseBody = client.get<String>("https://stackoverflow.com/")

注意事项

  • 响应的contentLength()可能返回null(比如服务器没返回Content-Length头),这种情况下contentLength会被设为0,进度函数里只能获取已下载字节数,总长度未知。
  • 以上代码完全适配你使用的Ktor 1.2.5版本,不同版本的API可能有差异,不要随意升级版本后直接复用。
  • 如果需要监控上传进度,逻辑会有所不同,但你的问题只涉及下载进度,所以这里就不展开啦。

内容的提问来源于stack exchange,提问作者Mirt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:26:26