[英]Java vertx 3.2 file upload using bodyhandler
java.lang.IllegalStateException: Request has already been read exception in vertx3.0. java.lang.IllegalStateException:在vertx3.0中,请求已被读取为异常。 I tried in many ways. 我尝试了很多方法。 The simple formupload is working fine. 简单的formupload工作正常。 But when i use body handler, it is throwing below exception. 但是,当我使用主体处理程序时,它会抛出以下异常。 Can anybody help ? 有人可以帮忙吗?
import io.vertx.core.AbstractVerticle;
import io.vertx.core.http.HttpHeaders;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.handler.BodyHandler;
/*
* @author Gogs
*/
public class TestServer extends AbstractVerticle {
// Convenience method so you can run it in your IDE
public static void main(String[] args) {
Runner.runExample(TestServer.class);
}
@Override
public void start() throws Exception {
Router router = Router.router(vertx);
// Enable multipart form data parsing
router.route().handler(BodyHandler.create());
router.route("/").handler(routingContext -> {
routingContext.response().putHeader("content-type", "text/html").end(
"<form action=\"/form\" ENCTYPE=\"multipart/form-data\" method=\"POST\" name=\"wibble\">\n" +
"choose a file to upload:<input type=\"file\" name=\"myfile\"/><br>"+
" <input type=\"submit\"/>"+
"</form>"
);
});
// handle the form
router.post("/form").handler(ctx -> {
ctx.request().setExpectMultipart(true);
ctx.request().uploadHandler(upload -> {
upload.exceptionHandler(cause -> {
ctx.response().setChunked(true).end("Upload failed");
});
upload.endHandler(v -> {
ctx.response().setChunked(true).end("Successfully uploaded to " + upload.filename());
});
// FIXME - Potential security exploit! In a real system you must check this filename
// to make sure you're not saving to a place where you don't want!
// Or better still, just use Vert.x-Web which controls the upload area.
upload.streamToFileSystem(upload.filename());
});
});
vertx.createHttpServer().requestHandler(router::accept).listen(8090);
}
}
Am seeing the below exception.
Feb 02, 2016 6:48:54 PM io.vertx.ext.web.impl.RoutingContextImplBase
SEVERE: Unexpected exception in route
java.lang.IllegalStateException: Request has already been read
at io.vertx.core.http.impl.HttpServerRequestImpl.checkEnded(HttpServerRequestImpl.java:426)
at io.vertx.core.http.impl.HttpServerRequestImpl.setExpectMultipart(HttpServerRequestImpl.java:322)
at io.vertx.ext.web.impl.HttpServerRequestWrapper.setExpectMultipart(HttpServerRequestWrapper.java:166)
at com.vertx.http.upload.TestServer.lambda$1(TestServer.java:43)
at io.vertx.ext.web.impl.RouteImpl.handleContext(RouteImpl.java:221)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:78)
at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:93)
at io.vertx.ext.web.handler.impl.BodyHandlerImpl$BHandler.doEnd(BodyHandlerImpl.java:155)
at io.vertx.ext.web.handler.impl.BodyHandlerImpl$BHandler.uploadEnded(BodyHandlerImpl.java:135)
at io.vertx.ext.web.handler.impl.BodyHandlerImpl$BHandler.lambda$null$35(BodyHandlerImpl.java:109)
at io.vertx.core.http.impl.HttpServerFileUploadImpl.notifyEndHandler(HttpServerFileUploadImpl.java:213)
at io.vertx.core.http.impl.HttpServerFileUploadImpl.lambda$handleComplete$165(HttpServerFileUploadImpl.java:206)
at io.vertx.core.file.impl.AsyncFileImpl.lambda$doClose$226(AsyncFileImpl.java:470)
at io.vertx.core.impl.ContextImpl.lambda$wrapTask$16(ContextImpl.java:335)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:358)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:357)
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:112)
at java.lang.Thread.run(Unknown Source)
You are reading the request body twice. 您正在阅读请求正文两次。 The first read is via BodyHandler
(see BodyHanderImpl
) and the second is by your own handler (see HttpServerRequestImpl
and HttpServerFileUploadImpl
). 第一次读取是通过BodyHandler
(请参阅BodyHanderImpl
),第二次是通过您自己的处理程序(请参阅HttpServerRequestImpl
和HttpServerFileUploadImpl
)。
BodyHandler
reads the body from the request fully and makes it available in context.body
. BodyHandler
完全从请求中读取正文,并使其在context.body
可用。 The way your router is configured: 路由器的配置方式:
router.route().handler(BodyHandler.create());
the body will be read completely on every single request handled by your router. 在路由器处理的每个单个请求中,都会完整读取正文。
Your handler is also reading the request body fully and writing its contents to the file system. 您的处理程序还将完全读取请求正文并将其内容写入文件系统。 Your router is configured to only execute your handler when a POST is made to /form
. 您的路由器配置为仅在对/form
进行POST时执行处理程序。
To recap the flow, when you submit the upload to /form
BodyHandler
is reading the request fully, storing the contents in context.body, and marking the request body as read. 回顾一下流程,当您向/form
提交上载时, BodyHandler
会完全读取请求,将内容存储在context.body中,并将请求正文标记为已读。 Your router matches the uri path to your upload handler and attempts to read the body again but since it has already been read the exception is raised. 您的路由器将uri路径匹配到您的上传处理程序,并尝试再次读取正文,但由于已经读取了正文,因此引发了异常。
Some thoughts... 一些想法...
If your intent is to write the uploaded file to the file system you really don't need BodyHandler configured in your router. 如果您打算将上载的文件写入文件系统,则实际上不需要在路由器中配置BodyHandler。 You would want to use BodyHandler when you needed the body in memory in order to process it in some way. 您需要在内存中需要主体以某种方式对其进行处理时,使用BodyHandler。 Unless you intend to execute a handler on very single request received by your router, you should not configure a handler without matching criteria (ie router.route().handler(...)
). 除非打算对路由器收到的单个请求执行处理程序,否则不应配置没有匹配条件(即router.route().handler(...)
)的router.route().handler(...)
。 A good use case for this type of handler is CookieHandler. 此类处理程序的一个很好的用例是CookieHandler。
http://grepcode.com/file/repo1.maven.org/maven2/io.vertx/vertx-web/3.0.0/io/vertx/ext/web/impl/RouterImpl.java#RouterImpl http://grepcode.com/file/repo1.maven.org/maven2/io.vertx/vertx-web/3.0.0/io/vertx/ext/web/impl/RouterImpl.java#RouterImpl
Gogs, I was looking at this code, and quite possible we could implement our own Router or something similar that could then be managed in the accept method... Gogs,我正在看这段代码,很可能我们可以实现自己的Router或类似的东西,然后可以在accept方法中对其进行管理...
我们可能可以创建自己的bodyhandler ...在配置文件中提供被忽略路由的列表: http ://grepcode.com/file/repo1.maven.org/maven2/io.vertx/vertx-web/3.0.0 /io/vertx/ext/web/handler/impl/BodyHandlerImpl.java#BodyHandlerImpl
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.