Quarkus Resteasy reactive能否无需等待文件全量上传即可启动处理流程
Quarkus Resteasy Reactive 流式上传边传边处理方案
结论
可以实现无需等待文件完全上传完成就启动处理流程,你当前遇到的必须等上传完成才能处理的问题,是默认POJO表单映射的缓存机制导致的。
原因说明
默认情况下你使用FileUpload做POJO表单映射时,Quarkus会先把所有multipart内容完整缓存到本地临时文件或内存后,才会注入表单对象到接口方法,因此你只能在文件全部上传完成后才能拿到form.file对象开始处理。
实现方案
方案1:直接使用Vert.x原生API流式处理(推荐,改造成本最低)
直接注入RoutingContext监听上传事件,不用POJO表单映射,收到分片数据就可以立即处理:
import io.vertx.ext.web.RoutingContext import jakarta.ws.rs.core.Context import jakarta.ws.rs.core.MediaType import jakarta.ws.rs.Consumes import jakarta.ws.rs.POST import jakarta.ws.rs.Path import jakarta.ws.rs.core.Response @Path("/upload") class UploadResource { @POST @Consumes(MediaType.MULTIPART_FORM_DATA) suspend fun upload(@Context routingContext: RoutingContext): Response { val request = routingContext.request() // 开启multipart解析 request.setExpectMultipart(true) // 监听文本表单项解析完成事件 request.formAttributeHandler { attr -> // 收到文本表单项就可以直接处理,不用等文件上传完成 when(attr.key) { "title" -> println("收到标题:${attr.value}") "description" -> println("收到描述:${attr.value}") } } // 监听文件part上传事件 request.uploadHandler { upload -> // upload为Vert.x原生HttpServerFileUpload对象,支持流式读取 println("开始接收文件:${upload.fileName()}") // 每收到一块文件分片就处理,比如实时写入对象存储、计算哈希、转码等 upload.handler { chunk -> println("收到文件分片,大小:${chunk.length()}") // 这里写你的分片处理逻辑 } // 当前文件part接收完成回调 upload.endHandler { println("文件${upload.fileName()} 接收完成") } } return Response.accepted().build() } }
你提到的AsyncFile能力可以直接通过pipeTo方法实现,和流式下载体验一致:
// 直接把上传流异步写入本地文件,不需要等完整文件加载到内存 upload.pipeTo(vertx.fileSystem().openAsync("/path/to/save/file", OpenOptions().setAppend(true)))
方案2:自定义FormDataParser适配POJO映射
如果你希望保留POJO表单映射的写法,可以自定义FormDataParser实现,Quarkus支持通过CDI注册自定义解析器覆盖默认实现,不过改造成本比方案1高,适合需要统一处理多上传接口的场景:
- 实现
org.jboss.resteasy.reactive.server.core.multipart.FormDataParser接口,重写解析逻辑,不缓存完整文件,直接把流封装到自定义的表单字段类型中 - 用
@Produces @Priority(1)注解注册自定义解析器的Bean,优先级高于默认实现即可。
注意事项
- 可以在
application.properties中配置quarkus.http.multipart.enable-file-uploads=true确保文件上传功能开启,同时调整quarkus.http.limits.max-chunk-size适配你的分片大小需求 - 原生Vert.x API自带响应式背压控制,只要你不强制把所有分片缓存到内存,不会出现OOM问题
内容的提问来源于stack exchange,提问作者ninja
相关产品推荐
相关产品推荐

