使用Functional Webflux上传文件

时间:2017-08-31 12:15:59

标签: spring-mvc spring-boot spring-web spring-webflux

我使用&#34;路由器Kotlin DSL&#34;对迁移到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]

stacktrace:

#include <cstring>
struct X { char a, b, c, d; };

void copy_assignment(char* p, X x) {
    *p++ = x.a;
    *p++ = x.b;
    *p++ = x.c;
    *p++ = x.d;
}

void copy_memcpy(char* p, X x) {
    memcpy(p, &x, sizeof(X));
}

1 个答案:

答案 0 :(得分:3)

您对类路径有以下依赖关系吗? Spring Framework需要这个来解析多部分请求。

ball100 = ball(100)

"py ball: {}, u ball: {}".format(*ball100)   # splat! Flatten the tuple

"py ball: {}, u ball: {}".format(ball100[0], ball100[1]) # DIY

"py ball: {ball[0]}, u ball: {ball[1]}".format(ball=ball100) # named arg