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

如何在KMM中使用Ktor高效上传1GB及以上大文件

在KMM中使用Ktor流式上传大文件(1GB+)的解决方案

核心思路

Ktor支持流式上传,无需将整个文件加载到内存(彻底避免内存溢出和效率低下问题)。由于KMM通用代码无法直接访问平台特定的File类(Android的Java File、iOS的NSFile),我们可以通过expect/actual机制封装平台相关的文件流读取逻辑,在通用代码中统一使用Ktor的Input类型完成上传。

步骤实现

1. 定义通用层的文件流读取接口

在commonMain中声明expect函数,用于跨平台获取文件的流式输入:

import io.ktor.utils.io.Input

expect suspend fun getFileInput(filePath: String): Input

2. 实现平台特定的文件流读取

Android平台(androidMain)

利用Java File类读取文件通道,转换为Ktor的Input:

import io.ktor.utils.io.Input
import io.ktor.utils.io.readChannel
import java.io.File

actual suspend fun getFileInput(filePath: String): Input {
    val file = File(filePath)
    if (!file.exists()) error("目标文件不存在:$filePath")
    return file.readChannel().toInput()
}

iOS平台(iosMain)

利用iOS的NSInputStream读取文件,转换为Ktor的Input:

import io.ktor.utils.io.Input
import io.ktor.utils.io.toInput
import platform.Foundation.NSInputStream
import platform.Foundation.NSURL

actual suspend fun getFileInput(filePath: String): Input {
    val fileUrl = NSURL.fileURLWithPath(filePath)
    val inputStream = NSInputStream.inputStreamWithURL(fileUrl) ?: error("无法打开文件流:$filePath")
    inputStream.open()
    return inputStream.toInput()
}

3. 通用代码中实现流式上传

在通用层调用上述函数获取文件流,通过Ktor的formData完成上传:

import io.ktor.client.HttpClient
import io.ktor.client.request.post
import io.ktor.client.request.setBody
import io.ktor.client.statement.HttpResponse
import io.ktor.http.HttpHeaders
import io.ktor.http.content.formData
import io.ktor.http.content.headers

// 初始化Ktor客户端(根据平台配置对应引擎,如Android用OkHttp、iOS用Darwin)
val ktorClient = HttpClient {
    // 可添加序列化、日志等插件
}

suspend fun uploadLargeFile(filePath: String, uploadEndpoint: String): HttpResponse {
    val fileInput = getFileInput(filePath)
    val fileName = filePath.substringAfterLast("/") // 提取文件名

    return ktorClient.post(uploadEndpoint) {
        // 可选:监听上传进度
        onUpload { bytesSentTotal, contentLength ->
            val progress = bytesSentTotal.toDouble() / contentLength.toDouble()
            // 此处可更新UI或记录上传进度
        }

        setBody(formData {
            append(
                key = "file",
                value = fileInput,
                headers = headers {
                    append(HttpHeaders.ContentDisposition, "form-data; name=\"file\"; filename=\"$fileName\"")
                    append(HttpHeaders.ContentType, "application/octet-stream") // 根据文件类型调整
                }
            )
            // 可附加其他表单字段
            append("uploadSource", "KMM")
        })
    }
}

关键说明

  • 流式上传优势:使用Input类型时,Ktor会逐块读取文件内容并发送,不会将整个文件加载到内存,完全适配1GB+的大文件上传场景。
  • 平台兼容性:expect/actual机制屏蔽了平台文件API的差异,通用代码无需关心底层实现细节。
  • 进度监听:通过onUpload回调可以实时获取上传进度,方便实现进度条等交互功能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 04:12:49