Cameleer

FTP component

The ftp component downloads files from and uploads files to an FTP server, polling a remote directory for new files.

Scheme: ftp: · Crate: cameleer-protocols · Cargo feature: protocols · Consumer: yes · Producer: yes · Apache Camel: FTP

The options and headers follow the file component. For TLS use ftps; for SSH use sftp.

When to use it

  • Collect files that remote sites, partners or machines drop on an FTP server.
  • Upload exports and reports to a partner's FTP server.
  • Move files from FTP into object storage, a database or a message broker.

URI format

text
ftp://[username@]host[:port]/directory[?options]

The directory is relative to the login directory; ftp://host//abs/dir is absolute. The default port is 21.

Example

Collect XML orders that a partner leaves in outgoing/, save them locally, and move each file into outgoing/.archive on the server once it has been saved.

yaml example: ftp-collect-orders
- route:
    id: collect-orders
    from:
      uri: "ftp://{{env:FTP_USER:camel}}@{{env:FTP_HOST:localhost:21}}/outgoing?password={{env:FTP_PASSWORD:changeme}}&passiveMode=true&include=.*\\.xml&move=.archive&delay=10000"
      steps:
        - log: "received ${file:name} from ${header.CamelFileHost}"
        - to: "file:{{env:LOCAL_DIR:received}}"

Rust DSL

rust
fn collect_orders_route(b: &mut RouteBuilder, ftp: &str, password: &str, local_dir: &str) {
    b.from(&format!("ftp://{}/outgoing?password={}&passiveMode=true&include=.*\\.xml&move=.archive&delay=10000", ftp, password))
        .route_id("collect-orders")
        .log("received ${file:name} from ${header.CamelFileHost}")
        .to(&format!("file:{}", local_dir));
}

Options

Connection:

optiondefaultdescription
username, passwordanonymousLogin (also user@ in the URI).
passiveModefalsePassive mode (needed behind NAT and most firewalls). false uses active mode (PORT/EPRT).
binaryfalseTYPE I; false transfers in ASCII mode with line-ending conversion.
stepwisetrueCWD into each directory level.
disconnectfalseClose the connection after each poll or upload.
connectTimeout10sConnect timeout.
soTimeout5mControl connection read timeout.
timeout30sData connection timeout.
sendNooptrueCheck pooled connections with NOOP.
maximumReconnectAttempts, reconnectDelay3, 1sReconnects.
throwExceptionOnConnectFailedfalseFail the poll on connect errors.
siteCommandSITE commands after login (one per line).
autoCreatetrueCreate the remote directory.
charsetText encoding of bodies.

Consumer: delay (500 ms), initialDelay (1000 ms) and the scheduler options, noop, delete, move, moveFailed, preMove, include, exclude, includeExt, excludeExt, antInclude, antExclude, antFilterCaseSensitive, fileName, recursive, minDepth, maxDepth, maxMessagesPerPoll, sortBy, idempotent, idempotentKey, idempotentRepository, download (false = headers only), localWorkDirectory (stream downloads to a local file instead of memory), resumeDownload (continue partial downloads, needs localWorkDirectory), streamDownload (body is a stream handle), ignoreFileNotFoundOrPermissionError, readLock (none, changed, rename, idempotent, idempotent-changed, idempotent-rename) with readLockCheckInterval (5s), readLockTimeout (20s), readLockMinLength, readLockMinAge.

Producer: fileName, fileExist (Override, Append, Fail, Ignore, Move with moveExisting, TryRename), tempFileName, tempPrefix, eagerDeleteTargetFile, allowNullBody, flatten, doneFileName.

As in Apache Camel, consumed files stay on the server unless delete, move, noop or idempotent is set. Options such as account, chmod, bufferSize, fastExistsCheck and the ftpClient.* group are accepted and ignored.

Message headers

headerdirectiondescription
CamelFileNameout / inRelative file name; producer: target name.
CamelFileNameOnly, CamelFileAbsolutePath, CamelFileRelativePath, CamelFilePath, CamelFileParentoutPath details.
CamelFileLength, CamelFileLastModifiedoutSize and time.
CamelFileHostoutServer host.
CamelFileLocalWorkPathoutLocal copy with localWorkDirectory.
CamelFtpReplyCode, CamelFtpReplyStringoutLast FTP reply.
CamelFtpResumedFromoutOffset a resumed download continued from.
CamelFileNameProducedoutProducer: the remote path written.
CamelOverruleFileNameinProducer: overrides the name once.

Run it with Docker

sh
docker run --rm --user "$(id -u):$(id -g)" -e FTP_HOST=ftp.partner.example -e FTP_USER -e FTP_PASSWORD \
  -e LOCAL_DIR=/data/received -v "$PWD:/data" \
  -v "$PWD/collect-orders.camel.yaml:/routes/collect-orders.camel.yaml:ro" \
  pmsudhi/cameleer run /routes/collect-orders.camel.yaml

Common questions

How do I upload a file to FTP?

to: ftp://user@host/incoming?password=...&passiveMode=true; the name comes from the CamelFileName header or fileName. Add tempPrefix=.part- so the partner never reads a partial file.

My downloads hang or time out. What should I check?

Most servers behind NAT or a firewall need passiveMode=true.

How do I download large files without holding them in memory?

Set localWorkDirectory=/tmp/ftp-work (and resumeDownload=true to continue interrupted transfers), or streamDownload=true.

How do I avoid picking up a file that is still uploading?

readLock=changed waits until the size and time stop changing; readLock=rename checks that the file can be renamed.

Found a problem?

If something on this page doesn't match what Cameleer does, or you hit a bug while building with it, please help fix it, whether you are a person or a coding agent: open an issue that describes what you saw, then fork the repository, fix it, add or update a test, run cargo test --workspace, and open a pull request. CONTRIBUTING.md explains the ground rules.

Edit this page on GitHub