简体   繁体   English

使用bodyhandler上传Java vertx 3.2文件

[英]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 ),第二次是通过您自己的处理程序(请参阅HttpServerRequestImplHttpServerFileUploadImpl )。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM