【问题标题】:MultiPart File Upload with Quarkus / Kotlin使用 Quarkus / Kotlin 上传多部分文件
【发布时间】:2021-04-04 17:14:30
【问题描述】:

我正在尝试在 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 的一个奇怪之处。

【问题讨论】:

    标签: kotlin resteasy quarkus


    【解决方案1】:

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

    @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 获取数据,而不是自动构造对象。希望有人能够阐明为什么需要这种解决方法,或者是否有更好的解决方案。

    【讨论】:

    • 从 Quarkus 2.2.3.Final 开始,使用带有空构造函数的 Kotlin 类有效。它也适用于最新的异步 RestEasy @RestFrom 注解。遗憾的是,它还不适用于数据类。
    【解决方案2】:

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

    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 :)

    希望对您有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-13
      • 2021-01-19
      • 2013-03-02
      • 1970-01-01
      • 1970-01-01
      • 2019-10-06
      • 2020-05-27
      • 2013-05-08
      相关资源
      最近更新 更多