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
相关产品推荐
相关产品推荐

