问题描述
我正在尝试在 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 :)
希望有帮助!