为什么 MultipartEntityBuilder 抛出 org.apache.http.ContentTooLongException?
Why MultipartEntityBuilder throws org.apache.http.ContentTooLongException?
我有一个简单的 Apache Camel 路由,它从队列中获取序列化文件并将其发送到一些外部资源:
public class MyRouteBuilder extends RouteBuilder {
@Override
public void configure() throws Exception {
from("activemq:alfresco-queue")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntityBuilder.addPart("file", new ByteArrayBody(exchange.getIn().getBody(byte[].class),
exchange.getIn().getHeader("fileName", String.class)));
exchange.getIn().setBody(multipartEntityBuilder.build().getContent());
}
})
.setHeader(Exchange.HTTP_METHOD, constant(org.apache.camel.component.http4.HttpMethods.POST))
.to("http4://vm-alfce5-31.....com:8080/alfresco/s/someco/queuefileuploader?guest=true")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
System.out.println("The response code is: " +
exchange.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE));
}
});
}
}
蓝图配置文件:
<?xml version="1.0"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">
<bean id="myRouteBuilder" class="org.fusesource.example.MyRouteBuilder"/>
<camelContext id="blueprintContext" trace="false" xmlns="http://camel.apache.org/schema/blueprint">
<routeBuilder ref="myRouteBuilder"/>
</camelContext>
</blueprint>
我的 OSGi 包在 JBoss FUSE ESB 中运行。
当我在 1-3 KB
内发送文件时,一切正常。如果文件较大(例如 4KB
),我会收到以下错误消息:
Failed delivery for (MessageId: ID:63-DP-TAV-51262-1531978204588-1:1:1:1:1
on ExchangeId: ID-63-DP-TAV-64708-1531973651576-0-3).
Exhausted after delivery attempt:
1 caught: org.apache.http.ContentTooLongException:
Content length is too long: 3301060
此调用发生此异常:
exchange.getIn().setBody(multipartEntityBuilder.build().getContent());
堆栈跟踪如下所示:
org.apache.http.ContentTooLongException: Content length is too long: 3301060
at org.apache.http.entity.mime.MultipartFormEntity.getContent(MultipartFormEntity.java:103)[commons-codec:commons-codec:1.9 org.apache.httpcomponents:fluent-hc:4.5.2 org.apache.httpcomponents:httpclient-cache:4.5.2 org.apache.httpcomponents:httpclient-osgi:4.5.2 org.apache.httpcomponents:httpclient:4.5.2 org.apache.httpcomponents:httpmime:4.5.2]
at org.fusesource.example.MyRouteBuilder.process(MyRouteBuilder.java:37)[org.fusesource.example:camel-basic:1.0-SNAPSHOT]
at org.apache.camel.processor.DelegateSyncProcessor.process(DelegateSyncProcessor.java:63)[org.apache.camel:camel-core:2.17.0.redhat-630187 com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2]
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:77)[org.apache.camel:camel-core:2.17.0.redhat-630187 com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2]
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:468)[org.apache.camel:camel-core:2.17.0.redhat-630187 com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2]
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:196)[org.apache.camel:camel-core:2.17.0.redhat-630187 com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2]
at org.apache.camel.processor.Pipeline.process(Pipeline.java:121)[org.apache.camel:camel-core:2.17.0.redhat-630187 com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2]
at org.apache.camel.processor.Pipeline.process(Pipeline.java:83)[org.apache.camel:camel-core:2.17.0.redhat-630187 com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2]
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:196)[org.apache.camel:camel-core:2.17.0.redhat-630187 com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2]
at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:109)[org.apache.camel:camel-core:2.17.0.redhat-630187 com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2]
at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:91)[org.apache.camel:camel-core:2.17.0.redhat-630187 com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2]
at org.apache.camel.component.jms.EndpointMessageListener.onMessage(EndpointMessageListener.java:112)[org.apache.camel:camel-jms:2.17.0.redhat-630187]
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:555)[org.apache.servicemix.bundles:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:515)[org.apache.servicemix.bundles:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:485)[org.apache.servicemix.bundles:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:325)[org.apache.servicemix.bundles:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:263)[org.apache.servicemix.bundles:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1103)[org.apache.servicemix.bundles:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1095)[org.apache.servicemix.bundles:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:992)[org.apache.servicemix.bundles:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)[:1.8.0_121]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)[:1.8.0_121]
at java.lang.Thread.run(Thread.java:745)[:1.8.0_121]
为什么 MultipartEntityBuilder
抛出 org.apache.http.ContentTooLongException
?我在哪里可以设置传递文件的最大大小?
这是 MultipartFormEntity#getContent
中编码的 25kB 硬限制。不要对可能超过此限制的请求使用此方法,请改用 HttpEntity#writeTo
。
但是使用 Apache Camel 你不需要自己做,HttpEntity
将在 camel-http4
组件中自动转换为 InputStream
。
直接将HttpEntity
设置为body:
exchange.getIn().setBody(multipartEntityBuilder.build());
我 运行 遇到了同样的问题并按如下方式解决了它:
// Assuming you created a MultipartEntityBuilder object above
HttpEntity multipartBody = multipartEntityBuilder.build();
// Header required to process multipart content
exchange.getIn().setHeader(Exchange.CONTENT_TYPE, multipartBody.getContentType().getValue());
// MultipartFormEntity#getContent method has a hard limit of 25kB
if (multipartBody.getContentLength() <= 25 * 1024) {
exchange.getIn().setBody(multipartBody.getContent());
}
// Manually creating input stream to overcome limit
else {
final ByteArrayOutputStream os = new ByteArrayOutputStream();
multipartBody.writeTo(os);
os.flush();
exchange.getIn().setBody(new ByteArrayInputStream(os.toByteArray()));
}
我有一个简单的 Apache Camel 路由,它从队列中获取序列化文件并将其发送到一些外部资源:
public class MyRouteBuilder extends RouteBuilder {
@Override
public void configure() throws Exception {
from("activemq:alfresco-queue")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntityBuilder.addPart("file", new ByteArrayBody(exchange.getIn().getBody(byte[].class),
exchange.getIn().getHeader("fileName", String.class)));
exchange.getIn().setBody(multipartEntityBuilder.build().getContent());
}
})
.setHeader(Exchange.HTTP_METHOD, constant(org.apache.camel.component.http4.HttpMethods.POST))
.to("http4://vm-alfce5-31.....com:8080/alfresco/s/someco/queuefileuploader?guest=true")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
System.out.println("The response code is: " +
exchange.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE));
}
});
}
}
蓝图配置文件:
<?xml version="1.0"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">
<bean id="myRouteBuilder" class="org.fusesource.example.MyRouteBuilder"/>
<camelContext id="blueprintContext" trace="false" xmlns="http://camel.apache.org/schema/blueprint">
<routeBuilder ref="myRouteBuilder"/>
</camelContext>
</blueprint>
我的 OSGi 包在 JBoss FUSE ESB 中运行。
当我在 1-3 KB
内发送文件时,一切正常。如果文件较大(例如 4KB
),我会收到以下错误消息:
Failed delivery for (MessageId: ID:63-DP-TAV-51262-1531978204588-1:1:1:1:1
on ExchangeId: ID-63-DP-TAV-64708-1531973651576-0-3).
Exhausted after delivery attempt:
1 caught: org.apache.http.ContentTooLongException:
Content length is too long: 3301060
此调用发生此异常:
exchange.getIn().setBody(multipartEntityBuilder.build().getContent());
堆栈跟踪如下所示:
org.apache.http.ContentTooLongException: Content length is too long: 3301060
at org.apache.http.entity.mime.MultipartFormEntity.getContent(MultipartFormEntity.java:103)[commons-codec:commons-codec:1.9 org.apache.httpcomponents:fluent-hc:4.5.2 org.apache.httpcomponents:httpclient-cache:4.5.2 org.apache.httpcomponents:httpclient-osgi:4.5.2 org.apache.httpcomponents:httpclient:4.5.2 org.apache.httpcomponents:httpmime:4.5.2]
at org.fusesource.example.MyRouteBuilder.process(MyRouteBuilder.java:37)[org.fusesource.example:camel-basic:1.0-SNAPSHOT]
at org.apache.camel.processor.DelegateSyncProcessor.process(DelegateSyncProcessor.java:63)[org.apache.camel:camel-core:2.17.0.redhat-630187 com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2]
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:77)[org.apache.camel:camel-core:2.17.0.redhat-630187 com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2]
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:468)[org.apache.camel:camel-core:2.17.0.redhat-630187 com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2]
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:196)[org.apache.camel:camel-core:2.17.0.redhat-630187 com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2]
at org.apache.camel.processor.Pipeline.process(Pipeline.java:121)[org.apache.camel:camel-core:2.17.0.redhat-630187 com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2]
at org.apache.camel.processor.Pipeline.process(Pipeline.java:83)[org.apache.camel:camel-core:2.17.0.redhat-630187 com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2]
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:196)[org.apache.camel:camel-core:2.17.0.redhat-630187 com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2]
at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:109)[org.apache.camel:camel-core:2.17.0.redhat-630187 com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2]
at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:91)[org.apache.camel:camel-core:2.17.0.redhat-630187 com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2]
at org.apache.camel.component.jms.EndpointMessageListener.onMessage(EndpointMessageListener.java:112)[org.apache.camel:camel-jms:2.17.0.redhat-630187]
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:555)[org.apache.servicemix.bundles:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:515)[org.apache.servicemix.bundles:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:485)[org.apache.servicemix.bundles:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:325)[org.apache.servicemix.bundles:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:263)[org.apache.servicemix.bundles:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1103)[org.apache.servicemix.bundles:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1095)[org.apache.servicemix.bundles:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:992)[org.apache.servicemix.bundles:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)[:1.8.0_121]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)[:1.8.0_121]
at java.lang.Thread.run(Thread.java:745)[:1.8.0_121]
为什么 MultipartEntityBuilder
抛出 org.apache.http.ContentTooLongException
?我在哪里可以设置传递文件的最大大小?
这是 MultipartFormEntity#getContent
中编码的 25kB 硬限制。不要对可能超过此限制的请求使用此方法,请改用 HttpEntity#writeTo
。
但是使用 Apache Camel 你不需要自己做,HttpEntity
将在 camel-http4
组件中自动转换为 InputStream
。
直接将HttpEntity
设置为body:
exchange.getIn().setBody(multipartEntityBuilder.build());
我 运行 遇到了同样的问题并按如下方式解决了它:
// Assuming you created a MultipartEntityBuilder object above
HttpEntity multipartBody = multipartEntityBuilder.build();
// Header required to process multipart content
exchange.getIn().setHeader(Exchange.CONTENT_TYPE, multipartBody.getContentType().getValue());
// MultipartFormEntity#getContent method has a hard limit of 25kB
if (multipartBody.getContentLength() <= 25 * 1024) {
exchange.getIn().setBody(multipartBody.getContent());
}
// Manually creating input stream to overcome limit
else {
final ByteArrayOutputStream os = new ByteArrayOutputStream();
multipartBody.writeTo(os);
os.flush();
exchange.getIn().setBody(new ByteArrayInputStream(os.toByteArray()));
}