使用功能性 Webflux 上传文件
Posted
技术标签:
【中文标题】使用功能性 Webflux 上传文件【英文标题】:File Upload with Functional Webflux 【发布时间】:2018-02-09 09:33:33 【问题描述】:我正在使用“Router Kotlin DSL”对迁移到 Spring WebFlux(和 Spring Boot)的功能变体进行原型设计。现在我需要一些提示以使用 MIME 类型 multipart/form-data
而不是例如文件上传。 PUT
使用application/json
处理一些数据。
当我像这样定义一个简单的路由器函数和一个处理程序时,我会得到下面的堆栈跟踪:
fun routes(handler: MultimediaHandler) = router
(accept(MediaType.MULTIPART_FORM_DATA) and "/multimedia").nest
PUT("/id", handler::upload)
class MultimediaHandler
fun upload(request: ServerRequest): Mono<ServerResponse>
val id = request.pathVariable("id")
return noContent().build()
堆栈跟踪:
13:43:29.713 ERROR [i.u.request] [XNIO-1 I/O-3] UT005071: Undertow request failed HttpServerExchange PUT /multimedia/00000000-0000-0000-0000-000000000
001 request Connection=[Keep-Alive], Accept-Encoding=[gzip,deflate], Content-Length=[1672], Content-Type=[multipart/form-data; boundary=-mJAzUqZoGk2nc
N1Rch4O4-KGbTExkAmQ7A], User-Agent=[Apache-HttpClient/4.5.2 (Java/1.8.0_144)], Host=[localhost:8444] response
java.lang.IllegalStateException: No multipart HttpMessageReader.
at org.springframework.web.server.adapter.DefaultServerWebExchange.lambda$initMultipartData$3(DefaultServerWebExchange.java:144) ~[spring-web-5.0.0.RC3.jar:5.0.0.RC3]
at java.util.Optional.orElseThrow(Optional.java:290) ~[?:1.8.0_144]
at org.springframework.web.server.adapter.DefaultServerWebExchange.initMultipartData(DefaultServerWebExchange.java:144) ~[spring-web-5.0.0.RC3.jar:5.0.0.RC3]
at org.springframework.web.server.adapter.DefaultServerWebExchange.<init>(DefaultServerWebExchange.java:109) ~[spring-web-5.0.0.RC3.jar:5.0.0.RC3]
at org.springframework.web.server.adapter.HttpWebHandlerAdapter.createExchange(HttpWebHandlerAdapter.java:167) ~[spring-web-5.0.0.RC3.jar:5.0.0.RC3]
at org.springframework.web.server.adapter.HttpWebHandlerAdapter.handle(HttpWebHandlerAdapter.java:156) ~[spring-web-5.0.0.RC3.jar:5.0.0.RC3]
at org.springframework.http.server.reactive.UndertowHttpHandlerAdapter.handleRequest(UndertowHttpHandlerAdapter.java:71) ~[spring-web-5.0.0.RC3.jar:5.0.0.RC3]
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:332) [undertow-core-1.4.19.Final.jar:1.4.19.Final]
at io.undertow.server.protocol.http.HttpReadListener.handleEventWithNoRunningRequest(HttpReadListener.java:254) [undertow-core-1.4.19.Final.jar:1.4.19.Final]
at io.undertow.server.protocol.http.HttpReadListener.handleEvent(HttpReadListener.java:136) [undertow-core-1.4.19.Final.jar:1.4.19.Final]
at io.undertow.server.protocol.http.HttpOpenListener.handleEvent(HttpOpenListener.java:148) [undertow-core-1.4.19.Final.jar:1.4.19.Final]
at io.undertow.server.protocol.http.AlpnOpenListener$AlpnConnectionListener.handleEvent(AlpnOpenListener.java:357) [undertow-core-1.4.19.Final.jar:1.4.19.Final]
at io.undertow.server.protocol.http.AlpnOpenListener$AlpnConnectionListener.handleEvent(AlpnOpenListener.java:308) [undertow-core-1.4.19.Final.jar:1.4.19.Final]
at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92) [xnio-api-3.5.1.Final.jar:3.5.1.Final]
at org.xnio.conduits.ReadReadyHandler$ChannelListenerHandler.readReady(ReadReadyHandler.java:66) [xnio-api-3.5.1.Final.jar:3.5.1.Final]
at io.undertow.protocols.ssl.SslConduit$SslReadReadyHandler.readReady(SslConduit.java:1140) [undertow-core-1.4.19.Final.jar:1.4.19.Final]
at org.xnio.nio.NiosocketConduit.handleReady(NioSocketConduit.java:89) [xnio-nio-3.5.1.Final.jar:3.5.1.Final]
at org.xnio.nio.WorkerThread.run(WorkerThread.java:571) [xnio-nio-3.5.1.Final.jar:3.5.1.Final]
【问题讨论】:
【参考方案1】:你的类路径有以下依赖吗? Spring Framework 需要它来解析多部分请求。
<dependency>
<groupId>org.synchronoss.cloud</groupId>
<artifactId>nio-multipart-parser</artifactId>
<version>...</version>
</dependency>
【讨论】:
谢谢,现在错误消失了。仅供参考,只要我将 Spring Cloud 和 Spring Boot 与 Spring MVC 一起使用,就不需要这种依赖关系。我刚刚将 MultipartFile 与 @RequestParam 一起使用。 那是因为它使用标准的 servlet 多部分支持。这里没有这样的东西。以上是关于使用功能性 Webflux 上传文件的主要内容,如果未能解决你的问题,请参考以下文章
WebFlux WebClient 在分段上传期间将整个文件加载到直接缓冲内存中
webflux下整合Mendmix文件上传组件上传文件到阿里云
webflux下整合Mendmix文件上传组件上传文件到阿里云
Webflux multipart/form-data,启用 csrf,有和没有文件上传获取 Invalid CSRF Token