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

Kotlin/Ktor中自定义Multipart.FormData转换器的convertForReceive如何实现

自定义Multipart.FormData转换器convertForReceive实现方案

完整转换器代码

object CustomMultipartConverter: ContentConverter {

    override suspend fun convertForReceive(context: PipelineContext<ApplicationReceiveRequest, ApplicationCall>): Any? {
        val call = context.context
        // 获取要反序列化的目标类型
        val targetType = context.subject.type.jvmErasure
        // 仅处理我们定义的请求类,其他类型返回null交给其他转换器处理
        if (targetType != CreatePostRequest::class) return null

        // 接收multipart所有数据
        val multipart = call.receiveMultipart()
        var text: String? = null
        var imageFile: File? = null

        multipart.forEachPart { part ->
            when (part) {
                // 处理普通表单字段
                is PartData.FormItem -> {
                    if (part.name == "text") {
                        text = part.value
                    }
                    part.dispose()
                }
                // 处理文件上传项
                is PartData.FileItem -> {
                    if (part.name == "image") {
                        // 生成临时文件存储上传内容,你也可以自定义存储路径
                        val tempFile = Files.createTempFile("upload_", ".tmp").toFile()
                        part.streamProvider().use { input ->
                            tempFile.outputStream().use { output ->
                                input.copyTo(output)
                            }
                        }
                        imageFile = tempFile
                    }
                    part.dispose()
                }
                else -> part.dispose()
            }
        }

        // 校验必填字段
        if (text == null) {
            throw BadRequestException("缺少必填参数text")
        }
        // 构造目标类实例返回
        return CreatePostRequest(text = text!!, image = imageFile)
    }

    override suspend fun convertForSend(
        context: PipelineContext<Any, ApplicationCall>,
        contentType: ContentType,
        value: Any
    ): Any? {
        // 不需要Multipart响应的话直接返回null即可
        return null
    }
}

路由代码修正

你原有路由逻辑没有指定请求方法和处理块,修正后示例:

route("v1/posts") {
    authenticate {
        post("create") { // 新增post方法声明
            val authJWT = call.authentication.principal as JWTAtuh
            val request = call.receive<CreatePostRequest>()
            // 你的业务逻辑
            // 注意:业务处理完成后记得删除临时文件避免磁盘占用
            request.image?.delete()
            call.respond(HttpStatusCode.OK)
        }
    }
}

注意事项

  • 如果需要支持多种不同的Multipart请求类,可以结合Kotlin反射自动映射字段名和Part内容,无需为每个类单独写判断逻辑
  • 上传文件的存储路径、文件名、大小限制可以根据业务需求自行调整
  • 临时文件一定要在处理完成后手动删除,避免磁盘空间被占满
  • 可根据需要添加参数校验逻辑,比如文件类型、大小、text字段长度等校验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 08:15:01