使用 Quarkus / Kotlin 上传多部分文件

问题描述

我正在尝试在 Quarkus 中构建多部分文件上传 REST 路由(使用 Kotlin),但在路由映射方面存在问题。

从客户端,我发布了一个包含文本值和文件值的表单。

const formData = new FormData();
formData.append("text",text);
formData.append("file",files[0]);

fetch('http://localhost:8080/data',{
   method: 'POST',body: formData
})

从服务器端,我尝试按如下方式检索值。

class FormData(@FormParam("text") @PartType(MediaType.TEXT_PLAIN) var text:String,@FormParam("file") @PartType(MediaType.APPLICATION_OCTET_STREAM) var file:InputStream)

@Path("/data")
class FormUploadResource {

    @POST
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    fun upload(@MultipartForm form:FormData) {
        println(form.text)
        println(form.file)
    }
}

然而,当我执行端点时,我得到一个 org.jboss.resteasy.spi.ReaderException: java.lang.NoSuchMethodException: 错误

我已尝试确保正确接收文本和文件参数,并检查了带有以下代码的有效负载

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
fun upload(input:MultipartFormDataInput) {
    var map = input.getFormDataMap()
    map.entries.forEach {
        println("""${it.key} - ${it.value}""") 
        if (it.value is List<InputPart>) {
            it.value.forEach { ip ->
                println(""" --- ${ip.getMediaType()} """ ) 
            }
        }
    }
}

它说得对

text - [org.jboss.resteasy.plugins.providers.multipart.MultipartInputImpl$PartImpl@660c4317]
 --- text/plain;charset=UTF-8
file - [org.jboss.resteasy.plugins.providers.multipart.MultipartInputImpl$PartImpl@3aee346]
 --- application/octet-stream;charset=UTF-8

我认为 FormData 类有问题,RestEasy 没有自动映射到它。我曾尝试将“文件”的类型更改为 ByteArray 和 File,但它们也都失败了。

我一直在努力寻找 Kotlin 的具体答案,所以这也可能是 Kotlin 的一个奇怪之处。

解决方法

我不会将此答案标记为正确,因为我对解决方案不满意,但它至少有效。

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
fun upload(input:MultipartFormDataInput) {
    val map = input.getFormDataMap()
    val text = map.get("text")?.first()?.getBodyAsString() ?: ""
    val file = map.get("file")?.first()?.getBodyAsString() ?: ""

    println(form.text)
    println(form.file)
}

如您所见,我直接从 MultipartFormDataInput 获取数据,而不是自动构建对象。希望有人能够解释为什么需要这种解决方法,或者是否有更好的解决方案可用。

,

我刚刚解决了这个问题,根本没有显示任何日志。我设法让它工作,似乎需要一个空的构造函数:

class FormData() {
    @FormParam("text") @PartType(MediaType.TEXT_PLAIN)
    var text: String? = null

    @FormParam("file") @PartType(MediaType.APPLICATION_OCTET_STREAM) 
    var file: InputStream? = null
}

但是我一定还是遗漏了一些东西,因为

class FormData(
    @FormParam("text") @PartType(MediaType.TEXT_PLAIN) var text: String?,@FormParam("file") @PartType(MediaType.APPLICATION_OCTET_STREAM) var file: InputStream?
) {
    constructor() : this(null,null)
}

进入方法但不初始化值

编辑:在测试了像这样工作的二级构造函数和一级构造函数之后,

class FormData
{
    @FormParam("file")
    @PartType(MediaType.APPLICATION_OCTET_STREAM)
    var file: InputStream? = null

    constructor() {
        this.file = null
    }

}

似乎需要一个 EMPTY PRIMARY CONSTRUCTOR :)

希望有帮助!