首页 > 解决方案 > Vert.x Web (Scala):从路由器读取多部分文件上传作为流而不保存到磁盘

问题描述

我知道可以通过 Vert.x Web 处理文件上传,Router只需使用以下内容:

myRouter.post("/upload")
    .handler(BodyHandler.create("myUploadDirectory")))
    .handler { context =>
        // do something with the uploaded files and respond to the request
    }

但是,这会将文件保存在本地服务器(甚至可能是网络共享)上。暂时在磁盘上缓冲小文件并将它们分批移动到另一个存储可能非常好,但对于非常大的文件(例如,数 GB)则不能这样说。

例如,将文件上传读取为字节流并将其直接写入最终存储,然后能够优雅地处理失败和成功的好方法是Router什么?

代理上传这将避免使客户端可以公开访问存储,并且可能允许对上传过程进行更细粒度的控制,而不仅仅是在服务器上创建本地文件或公开对象/blob 存储。

编辑:

我知道另一种方法是做这样的事情,在使用 my 处理请求之前将文件上传作为特殊情况处理Router

      val myHttpServer = myVertx.createHttpServer()


      myHttpServer.requestHandler(request => {
        if(request.absoluteURI().contains("/upload")) {
          request.setExpectMultipart(true)
          request.handler { buffer =>
            // upload part of the file
          }
          request.endHandler { end =>
            // perform some action when the upload is done
          }
        } else
          myRouter.handle(request)
      })

但是,如您所见,它看起来非常混乱。Router.post()用 a或类似的东西处理它会更干净。

我是要解决这个问题还是什么?

我尝试执行以下操作无济于事(我只得到 HTTP 500,日志中没有有用的错误)。甚至没有exceptionHandler被解雇。

        myRouter.post("/upload")
          .handler { context =>
            context.request.setExpectMultipart(true)
            context.request.uploadHandler { upload =>
              upload.handler { buffer =>
                // send chunk to backend
              }
              upload.endHandler { _ =>
                // upload successful
              }
              upload.exceptionHandler { e =>
                // handle the exception
              }
            }
          }

解决方案:

所以事实证明,我在添加路线之前添加了BodyHandler一个。Router这是因为我希望能够在其他 POST 请求中接收 JSON 正文,并且不想.handler(BodyHandler.create())在每个接收 JSON 的路由之前都输入。

但是,正如课程名称中所述......然后处理了正文,这意味着我将无法将其添加到请求中。UploadHandler

标签: javascalamultipartform-datavert.x

解决方案


我对 Scala 不了解,但这里有一个 Java 解决方案:

router.post("/upload").handler(rc -> {
  HttpServerRequest req = rc.request();
  req.setExpectMultipart(true);
  req.uploadHandler(upload -> {
    upload.exceptionHandler(cause -> {
      req.response().setChunked(true).end("Upload failed");
    });

    upload.endHandler(v -> {
      req.response().setChunked(true).end("Successfully uploaded file");
    });
    upload.handler(buffer -> {
      // Send to backend
    });
  });
});

推荐阅读