java - 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
解决方案
我对 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
});
});
});
推荐阅读
- kafka-consumer-api - Spring Cloud Stream Kafka 消费者/生产者 API 恰好一次语义(事务性)
- database - 导入大约 130 个 informix 数据库后出现错误
- java - 有没有办法将 Flux 作为表单数据提供给 WebClient 的主体?
- nginx - Kubernetes Nginx Ingress 删除部分 URL
- java - 我有这种方法可以让每个已安装应用程序使用的数据移动
- javascript - 用 PHP 插入的 JavaScript 值返回错误
- c# - 链接不占用完整的 div
- javascript - 如何在不知道确切字符串的情况下获取数组中的特定元素
- neo4j - 将查询放入 foreach
- php - Laravel - 将 cookie 传递给服务提供者