Large payloads
Camel can move large files, such as several gigabytes, between components without loading them into memory. This does not happen with every configuration, though: a few defaults and a few route constructs load the whole message body into the heap. This page explains which ones, and how to configure the most common components to stream large payloads.
Stream caching
Stream caching is enabled by default, but spooling to disk is not. When a message body is a stream, such as an InputStream returned by a component, stream caching copies it into a re-readable cache the next time a processor needs the body. Without spooling, that cache is kept in memory, so a stream of several gigabytes ends up in the heap.
For routes that handle large payloads, choose one of the following:
-
Enable spooling, so bodies above the spool threshold (128 KB by default) are cached in a temporary file:
camel.main.streamCachingSpoolEnabled = true # a volume with room for the largest payload times the number of concurrent exchanges camel.main.streamCachingSpoolDirectory = /data/camel-spoolThe body can then be read many times, for example by redelivery, and the heap stays bounded. The cost is one full copy of the payload to the spool directory. In containers, make sure the spool directory is writable and large enough.
-
Disable stream caching for the route, so the stream is passed from component to component as-is:
from("sftp:...?streamDownload=true") .streamCache("false") .to("http:...");Nothing is copied, but the body can only be read once. Do not use steps that read the body again, such as redelivery, a
choiceon the body,multicast,wireTaporrecipientList.
A body that is a file (java.io.File, java.nio.file.Path, or the file of the File component) is not cached, as it can already be read many times. Keeping a large payload as a file is often the cheapest option.
Route steps that load the whole body
Even when the components stream, the following steps load the whole body into memory:
-
converting the body to a
Stringorbyte[], for example withconvertBodyTo(String.class) -
using
${body}in a Simple expression, including.log("${body}") -
unmarshalling the whole body with a data format, such as JSON or XML
-
tracing the body with the Tracer or the Backlog Tracer; the body is converted before it is clipped to the maximum number of characters
-
the Split EIP without
streaming()
To process a large file record by record, split it in streaming mode, for example split(body().tokenize("\n")).streaming().
Components
The following table describes how the most common components handle large payloads, and which options make them stream. When a stream is received, stream caching applies to it as described above.
| Component | Receiving (consumer, download) | Sending (producer, upload) |
|---|---|---|
The body is the file; it is not read until it is used. | A | |
By default the whole file is loaded into memory. Set | A | |
Not supported. | The whole body is loaded into memory. | |
By default ( | A file, or a stream whose length is known (a stream cache, or the | |
The blob is received as a stream. With | Same as AWS S3. For blobs, the length can also be given with the | |
With | Same as AWS S3. The length can also be given with the | |
MinIO loads the whole object into memory when the body is included. | Same as AWS S3. | |
The response is copied into a stream cache (a temporary file when spooling is enabled). With | A | |
By default the whole request body is loaded into memory. Multipart file uploads are written to temporary files, and a single uploaded file becomes the body. With | A | |
The whole response is loaded into memory. | The whole request body is loaded into memory, unless it is a Vert.x | |
The whole response is loaded into memory, up to | With |
Platform HTTP request size limits
The size of an uploaded request is limited by the runtime:
-
Camel Main and Camel JBang:
camel.server.maxBodySize. When it is not set, the Vert.x default of 10 MB applies. WithuseStreaming=truethis limit does not apply, so limit the size of requests in front of Camel if needed. -
Quarkus:
quarkus.http.limits.max-body-size, and thequarkus.http.body.*options for file uploads. See the Quarkus documentation. -
Spring Boot:
spring.servlet.multipart.max-file-sizeandspring.servlet.multipart.max-request-sizefor multipart uploads. See the Spring Boot documentation.
On Camel Main, Camel JBang and Quarkus, useStreaming=true does not accept multipart requests; use a separate endpoint for multipart uploads.
Examples
From SFTP to HTTP
Receive the remote file as a stream and send it on without copying it:
from("sftp:host/inbox?username=...&streamDownload=true")
.streamCache("false")
.to("http:backend/upload"); The HTTP producer sends the stream with chunked transfer encoding. Alternatively, keep stream caching and set localWorkDirectory on the SFTP endpoint, so the file is downloaded to disk and the body is a file.
From Platform HTTP to AWS S3
Multipart uploads are written to temporary files by the HTTP server, and the uploaded file is then sent to S3 from disk:
from("platform-http:/upload?httpMethodRestrict=POST")
.setHeader(AWS2S3Constants.KEY, header(Exchange.FILE_NAME))
.to("aws2-s3:my-bucket"); Raise the request size limit of the runtime, as described above.
For a raw request body (not multipart), enable spooling and use useStreaming=true:
from("platform-http:/upload?httpMethodRestrict=PUT&useStreaming=true")
.to("aws2-s3:my-bucket?keyName=upload.bin"); The request is written to the spool directory while it is received, and S3 uploads it from there with its known length.