Ktor Darwin引擎不支持分块数据读取问题求助
解决方案
修复Darwin引擎下的分块读取问题
Darwin引擎(基于iOS系统URLSession)默认会缓冲完整响应,导致无法逐块接收数据。只需在创建HttpClient时显式禁用响应缓冲,同时优化字符解码逻辑避免截断多字节UTF-8字符:
import io.ktor.client.HttpClient import io.ktor.client.engine.darwin.Darwin import io.ktor.client.request.preparePost import io.ktor.client.statement.body import io.ktor.utils.io.ByteReadChannel import io.ktor.utils.io.readAvailable import kotlin.native.Platform import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.launch import java.nio.ByteBuffer import kotlinx.io.charsets.Charsets private const val DEFAULT_BUFFER_SIZE: Int = 8 * 1024 internal val client = HttpClient { if (Platform.isIOS()) { engine(Darwin) { disableResponseBuffering = true } } // Android端保持OkHttp引擎默认配置即可 } fun readChunkedData(url: String, scope: CoroutineScope, onChunk: (String) -> Unit): Job { // 由调用方传入CoroutineScope,避免内部创建Scope导致内存泄漏 return scope.launch { client.preparePost(url).execute { response -> val channel = response.body<ByteReadChannel>() val decoder = Charsets.UTF_8.newDecoder() val buffer = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE) while (!channel.isClosedForRead) { val bytesRead = channel.readAvailable(buffer) if (bytesRead > 0) { buffer.flip() val chunk = decoder.decode(buffer).toString() buffer.clear() onChunk(chunk) } } // 处理解码器中剩余的未完成字符 decoder.flush().takeIf { it.isNotEmpty() }?.let { onChunk(it.toString()) } } } }
关键改动说明:
- 针对iOS平台的Darwin引擎配置
disableResponseBuffering = true,强制逐块返回响应数据 - 改用标准UTF-8解码器处理字节转字符串,解决原代码中截断多字节字符的问题
- 调整CoroutineScope的传入方式,优化内存管理
关于CIO引擎的TLS问题
CIO引擎在iOS原生平台的TLS支持不完善,官方未完成适配,因此不推荐在iOS端使用CIO。优先选择Darwin引擎,它基于系统原生URLSession,能完美兼容系统的TLS配置和会话管理,稳定性与兼容性更优。
内容的提问来源于stack exchange,提问作者Arsenius
相关产品推荐
相关产品推荐

