在 Vertx 中处理多部分表单
Handling multipart form in Vertx
我有一个包含一些文本字段和一些上传文件的多部分表单。我需要在 vertx 处理程序中处理这个多部分 post 请求,以便所有上传的文件(可变数量)都应该以块的形式读取(出于内存效率目的)。在我读取块(在 foreach 循环中)的那一刻,我想将其直接流式传输到文件中。对于带有文本字段的多部分,我只想将值存储到我的模型对象中。
我对 vertx 很陌生,因此正在寻找实现此目的的代码片段,但在 vertx 文档的任何地方都找不到它。
你应该看看 vertx-web。它完全包含您需要的内容:
router.route().handler(BodyHandler.create());
router.post("/some/path/uploads").handler(routingContext -> {
MultiMap attributes = routingContext.request().formAttributes();
// do something with the form data
Set<FileUpload> uploads = routingContext.fileUploads();
// Do something with uploads....
});
希望这会有所帮助。
您可以分别处理文本字段和文件。这可以简化您的处理过程。
request.handler(buffer -> {
// decode the text field here
// ...
}).uploadHandler(upload -> {
// read upload files in chunks here
// ...
}).endHandler(v -> {
// upload request end here
// ...
});
我找到了另一种实时解码多部分数据的方法。借助netty解码器。请参阅下面的代码片段:
// the netty decoder used to decode multipart data in real time
HttpPostMultipartRequestDecoder decoder = null;
// create the decoder with reflect method
private void createDecoder(HttpServerRequest wrapper) {
try {
Class<?> wrapperClass = Class.forName("io.vertx.ext.web.impl.HttpServerRequestWrapper");
Field delegateField = wrapperClass.getDeclaredField("delegate");
delegateField.setAccessible(true);
HttpServerRequestImpl request = (HttpServerRequestImpl) delegateField.get(wrapper);
Field requestField = request.getClass().getDeclaredField("request");
requestField.setAccessible(true);
HttpRequest httpRequest = (HttpRequest) requestField.get(request);
decoder = new HttpPostMultipartRequestDecoder(new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE),
httpRequest);
} catch (ClassNotFoundException | NoSuchFieldException | SecurityException | IllegalArgumentException
| IllegalAccessException ex) {
log.error("create decoder failed {}.", ex.getMessage());
}
log.info("create decoder finished. {}", decoder);
}
router.route().handler(BodyHandler.create());
router.post("/some/path/uploads").handler(routingContext -> {
// NOTE: in vertx, request is a class of 'HttpServerRequestWrapper'
HttpServerRequest requestWrapper = routingContext.request();
createDecoder(requestWrapper);
// decode the buffer in real time
request.handler(buffer -> {
decoder.offer(new DefaultHttpContent(buffer.getByteBuf()));
if (decoder.hasNext()) {
// get the attributes and other data
// ...
}
});
});
我有一个包含一些文本字段和一些上传文件的多部分表单。我需要在 vertx 处理程序中处理这个多部分 post 请求,以便所有上传的文件(可变数量)都应该以块的形式读取(出于内存效率目的)。在我读取块(在 foreach 循环中)的那一刻,我想将其直接流式传输到文件中。对于带有文本字段的多部分,我只想将值存储到我的模型对象中。
我对 vertx 很陌生,因此正在寻找实现此目的的代码片段,但在 vertx 文档的任何地方都找不到它。
你应该看看 vertx-web。它完全包含您需要的内容:
router.route().handler(BodyHandler.create());
router.post("/some/path/uploads").handler(routingContext -> {
MultiMap attributes = routingContext.request().formAttributes();
// do something with the form data
Set<FileUpload> uploads = routingContext.fileUploads();
// Do something with uploads....
});
希望这会有所帮助。
您可以分别处理文本字段和文件。这可以简化您的处理过程。
request.handler(buffer -> {
// decode the text field here
// ...
}).uploadHandler(upload -> {
// read upload files in chunks here
// ...
}).endHandler(v -> {
// upload request end here
// ...
});
我找到了另一种实时解码多部分数据的方法。借助netty解码器。请参阅下面的代码片段:
// the netty decoder used to decode multipart data in real time
HttpPostMultipartRequestDecoder decoder = null;
// create the decoder with reflect method
private void createDecoder(HttpServerRequest wrapper) {
try {
Class<?> wrapperClass = Class.forName("io.vertx.ext.web.impl.HttpServerRequestWrapper");
Field delegateField = wrapperClass.getDeclaredField("delegate");
delegateField.setAccessible(true);
HttpServerRequestImpl request = (HttpServerRequestImpl) delegateField.get(wrapper);
Field requestField = request.getClass().getDeclaredField("request");
requestField.setAccessible(true);
HttpRequest httpRequest = (HttpRequest) requestField.get(request);
decoder = new HttpPostMultipartRequestDecoder(new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE),
httpRequest);
} catch (ClassNotFoundException | NoSuchFieldException | SecurityException | IllegalArgumentException
| IllegalAccessException ex) {
log.error("create decoder failed {}.", ex.getMessage());
}
log.info("create decoder finished. {}", decoder);
}
router.route().handler(BodyHandler.create());
router.post("/some/path/uploads").handler(routingContext -> {
// NOTE: in vertx, request is a class of 'HttpServerRequestWrapper'
HttpServerRequest requestWrapper = routingContext.request();
createDecoder(requestWrapper);
// decode the buffer in real time
request.handler(buffer -> {
decoder.offer(new DefaultHttpContent(buffer.getByteBuf()));
if (decoder.hasNext()) {
// get the attributes and other data
// ...
}
});
});