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

dwbf0jvd  于 2023-08-07  发布在  Kotlin
关注(0)|答案(2)|浏览(143)

我试图在Quarkus中构建一个多部分文件上传REST路由(使用Kotlin),但路由Map有问题。
从客户端,我发布了一个包含文本值和文件值的表单。

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


我假设RestEasy没有自动Map到FormData类,这是因为FormData类出了问题。我试过将“file”的类型更改为ByteArray和File,它们都失败了。
我一直在努力寻找Kotlin的具体答案,所以这也可能是Kotlin的一个奇怪之处。

ycggw6v2

ycggw6v21#

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

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
    }

}


似乎需要一个空的主要构造器:)
希望它有帮助!

b0zn9rqh

b0zn9rqh2#

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

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

相关问题