Apache Camel - 多部分文件上传
Apache Camel - Multipart File upload
使用 Apache-Camel ESB,尝试将 xlsx 文件上传到 Spring Rest Web 应用程序。从 apache-camel ESB 上传失败。但是从邮递员上传工作正常。下面共享代码片段。
骆驼路由器中的处理器代码看起来像
from("file://data/PASInput").process(new Processor() {
@Override
public void process(Exchange exchange) throws Exception {
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
String filename = (String) exchange.getIn().getHeader(Exchange.FILE_NAME);
File file = exchange.getIn().getBody(File.class);
multipartEntityBuilder.addPart("file",
new FileBody(file, ContentType.MULTIPART_FORM_DATA, filename));
ByteArrayOutputStream out = new ByteArrayOutputStream();
multipartEntityBuilder.build().writeTo(out);
InputStream inputStream = new ByteArrayInputStream(out.toByteArray());
exchange.getOut().setBody(inputStream);
}
}).to("http://localhost:8080/Pastel/api/convertor/pas/pastel")
.log(LoggingLevel.ERROR, "RESPONSE BODY ${body}").end();
Pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>2.21.0.fuse-000077-redhat-1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-cxf</artifactId>
<version>2.21.0.fuse-000077-redhat-1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-http</artifactId>
<version>2.21.0.fuse-000077-redhat-1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-http4</artifactId>
<version>2.17.2</version>
</dependency>
错误
org.apache.camel.http.common.HttpOperationFailedException: HTTP operation failed invoking http://localhost:8080/Pastel/api/convertor/pas/pastel with statusCode: 500
at org.apache.camel.component.http.HttpProducer.populateHttpOperationFailedException(HttpProducer.java:274)
at org.apache.camel.component.http.HttpProducer.process(HttpProducer.java:183)
at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61)
at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:148)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:138)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:101)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
at org.apache.camel.component.file.GenericFileConsumer.processExchange(GenericFileConsumer.java:452)
at org.apache.camel.component.file.GenericFileConsumer.processBatch(GenericFileConsumer.java:219)
at org.apache.camel.component.file.GenericFileConsumer.poll(GenericFileConsumer.java:183)
at org.apache.camel.impl.ScheduledPollConsumer.doRun(ScheduledPollConsumer.java:174)
at org.apache.camel.impl.ScheduledPollConsumer.run(ScheduledPollConsumer.java:101)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
当我们使用邮递员访问网络服务时,没有错误。能够成功上传服务器。 Spring mvc 代码,
@RequestMapping(value = "/pas/pastel", method = RequestMethod.POST)
@ResponseBody
public void convertPASToPastel(HttpServletRequest request, HttpServletResponse response,
@RequestParam(value = "file") final MultipartFile pasFile) {
try {
System.out.print("Here");
}
}
您可能会在 Spring 后端日志中看到此错误消息:
org.springframework.web.multipart.MultipartException: Current request is not a multipart request.
您需要设置正确的 ContentType
header。如果您想以这种方式实现,请参考this 类似问题的解决方案。
但是如果你切换 co camel-http4
组件(你已经在 pom.xml 中有这个组件),你可以解决这个问题。该组件包含将 HttpEntity
转换为 InputStream
的逻辑。那么就可以直接设置HttpEntity
来交换body.
那么您的路线将如下所示:
from("file://data/PASInput").process(new Processor() {
@Override
public void process(Exchange exchange) throws Exception {
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
String filename = exchange.getIn().getHeader(Exchange.FILE_NAME, String.class);
File file = exchange.getIn().getBody(File.class);
multipartEntityBuilder.addPart("file",
new FileBody(file, ContentType.MULTIPART_FORM_DATA, filename));
exchange.getOut().setBody(multipartEntityBuilder.build());
}
}).to("http4://localhost:8080/Pastel/api/convertor/pas/pastel")
.log(LoggingLevel.ERROR, "RESPONSE BODY ${body}").end();
还有一张纸条。 切勿混用组件版本,始终使用与 Apache Camel 版本相同的组件。否则你会看到不可预测的结果。为什么在 Spring 控制器中有注解 @ResponseBody
,而方法是 void
?你不需要那个。
使用 Apache-Camel ESB,尝试将 xlsx 文件上传到 Spring Rest Web 应用程序。从 apache-camel ESB 上传失败。但是从邮递员上传工作正常。下面共享代码片段。
骆驼路由器中的处理器代码看起来像
from("file://data/PASInput").process(new Processor() { @Override public void process(Exchange exchange) throws Exception { MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create(); multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); String filename = (String) exchange.getIn().getHeader(Exchange.FILE_NAME); File file = exchange.getIn().getBody(File.class); multipartEntityBuilder.addPart("file", new FileBody(file, ContentType.MULTIPART_FORM_DATA, filename)); ByteArrayOutputStream out = new ByteArrayOutputStream(); multipartEntityBuilder.build().writeTo(out); InputStream inputStream = new ByteArrayInputStream(out.toByteArray()); exchange.getOut().setBody(inputStream); } }).to("http://localhost:8080/Pastel/api/convertor/pas/pastel") .log(LoggingLevel.ERROR, "RESPONSE BODY ${body}").end();
Pom.xml
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-spring-boot-starter</artifactId> <version>2.21.0.fuse-000077-redhat-1</version> </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-cxf</artifactId> <version>2.21.0.fuse-000077-redhat-1</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpmime</artifactId> <version>4.3.1</version> </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-http</artifactId> <version>2.21.0.fuse-000077-redhat-1</version> </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-http4</artifactId> <version>2.17.2</version> </dependency>
错误
org.apache.camel.http.common.HttpOperationFailedException: HTTP operation failed invoking http://localhost:8080/Pastel/api/convertor/pas/pastel with statusCode: 500 at org.apache.camel.component.http.HttpProducer.populateHttpOperationFailedException(HttpProducer.java:274) at org.apache.camel.component.http.HttpProducer.process(HttpProducer.java:183) at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61) at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:148) at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548) at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201) at org.apache.camel.processor.Pipeline.process(Pipeline.java:138) at org.apache.camel.processor.Pipeline.process(Pipeline.java:101) at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201) at org.apache.camel.component.file.GenericFileConsumer.processExchange(GenericFileConsumer.java:452) at org.apache.camel.component.file.GenericFileConsumer.processBatch(GenericFileConsumer.java:219) at org.apache.camel.component.file.GenericFileConsumer.poll(GenericFileConsumer.java:183) at org.apache.camel.impl.ScheduledPollConsumer.doRun(ScheduledPollConsumer.java:174) at org.apache.camel.impl.ScheduledPollConsumer.run(ScheduledPollConsumer.java:101) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
当我们使用邮递员访问网络服务时,没有错误。能够成功上传服务器。 Spring mvc 代码,
@RequestMapping(value = "/pas/pastel", method = RequestMethod.POST) @ResponseBody public void convertPASToPastel(HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "file") final MultipartFile pasFile) { try { System.out.print("Here"); } }
您可能会在 Spring 后端日志中看到此错误消息:
org.springframework.web.multipart.MultipartException: Current request is not a multipart request.
您需要设置正确的 ContentType
header。如果您想以这种方式实现,请参考this 类似问题的解决方案。
但是如果你切换 co camel-http4
组件(你已经在 pom.xml 中有这个组件),你可以解决这个问题。该组件包含将 HttpEntity
转换为 InputStream
的逻辑。那么就可以直接设置HttpEntity
来交换body.
那么您的路线将如下所示:
from("file://data/PASInput").process(new Processor() {
@Override
public void process(Exchange exchange) throws Exception {
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
String filename = exchange.getIn().getHeader(Exchange.FILE_NAME, String.class);
File file = exchange.getIn().getBody(File.class);
multipartEntityBuilder.addPart("file",
new FileBody(file, ContentType.MULTIPART_FORM_DATA, filename));
exchange.getOut().setBody(multipartEntityBuilder.build());
}
}).to("http4://localhost:8080/Pastel/api/convertor/pas/pastel")
.log(LoggingLevel.ERROR, "RESPONSE BODY ${body}").end();
还有一张纸条。 切勿混用组件版本,始终使用与 Apache Camel 版本相同的组件。否则你会看到不可预测的结果。为什么在 Spring 控制器中有注解 @ResponseBody
,而方法是 void
?你不需要那个。