Skip to main content

Triggers

The ballerina/ftp connector supports event-driven file processing through a polling-based listener. The ftp:Listener periodically monitors a configured directory on a remote FTP/SFTP server for file changes and delivers new file content to your service callbacks in the format you choose (bytes, text, JSON, XML, or CSV).

The connector exposes several components:

ComponentRole
ftp:ListenerPolls a remote FTP/SFTP directory at a configurable interval and detects new or deleted files.
ftp:ServiceHosts one or more remote functions that are invoked on file events. Multiple format-specific handlers can be combined on a single service to route different file types to different methods.
ftp:CallerAn FTP client passed to callbacks, enabling additional file operations (read, write, move, delete) within the handler.
ftp:FileInfoMetadata record describing a remote file such as path, name, size, timestamps, and attributes.

For action-based operations, see the Action Reference.


Listener

The ftp:Listener establishes the connection and manages event subscriptions.

Configuration

The listener supports the following connection strategy:

Config TypeDescription
ListenerConfigurationConfiguration for the FTP/SFTP listener including connection details, authentication, and polling settings.

ListenerConfiguration fields:

FieldTypeDefaultDescription
protocolProtocolFTPThe file transfer protocol to use (FTP, FTPS, or SFTP).
hoststring"127.0.0.1"Hostname or IP address of the FTP server.
portint21Port number of the FTP server. Typically 21 for FTP and FTPS explicit, and 990 for FTPS implicit.
authAuthConfiguration()Authentication settings, including credentials, SSH private key (SFTP), SSL/TLS configuration (FTPS), and preferred SFTP authentication methods.
pollingIntervaldecimal60.0Interval in seconds between directory polls.
userDirIsRootbooleanfalseWhether to treat the user's home directory as the root directory.
laxDataBindingbooleanfalseWhen true, enables relaxed data binding for JSON/XML: null values map to optional fields and missing fields map to null values.
connectTimeoutdecimal30.0Connection timeout in seconds.
socketConfigSocketConfig()Per-protocol socket timeouts: ftpDataTimeout (FTP data), ftpSocketTimeout (FTP control), and sftpSessionTimeout (SFTP session).
fileTransferModeFileTransferModeBINARYFile transfer mode (BINARY or ASCII).
retryConfigRetryConfig()Retry configuration for transient failures during file content retrieval. When set, failed reads are retried with exponential backoff before the error reaches the handler or onError. Polling itself is not retried.
proxyProxyConfiguration()Proxy / jump-host configuration (SFTP only).
sftpCompressionTransferCompression[][NO]Compression algorithms to negotiate (ZLIB, ZLIBOPENSSH, NO) (SFTP only).
sftpSshKnownHostsstring()Path to the SSH known_hosts file used for host key verification (SFTP only).
csvFailSafeFailSafeOptions()Fail-safe CSV processing for onFileCsv. When set, malformed rows are skipped and logged to a separate file in the current working directory instead of failing the handler.
coordinationCoordinationConfig()Distributed task coordination. When set, multiple listener members coordinate so that only one polls at a time and the others act as warm standby.
note

The deprecated fields path, fileNamePattern, fileAgeFilter, and fileDependencyConditions still exist on ListenerConfiguration but should not be used in new code. Configure these on the service via @ftp:ServiceConfig instead, see File Dependency and Trigger Conditions.

Initializing the listener

Using FTP with username and password:

import ballerina/ftp;

configurable string host = ?;
configurable int port = ?;
configurable string username = ?;
configurable string password = ?;

listener ftp:Listener ftpListener = check new (
protocol = ftp:FTP,
host = host,
port = port,
auth = {
credentials: {
username: username,
password: password
}
},
pollingInterval = 10.0
);

Using SFTP with private key authentication:

import ballerina/ftp;

configurable string host = ?;
configurable int port = ?;
configurable string username = ?;
configurable string privateKeyPath = ?;
configurable string privateKeyPassword = ?;

listener ftp:Listener sftpListener = check new (
protocol = ftp:SFTP,
host = host,
port = port,
auth = {
credentials: {
username: username
},
privateKey: {
path: privateKeyPath,
password: privateKeyPassword
}
},
pollingInterval = 10.0
);

Service

An ftp:Service is a Ballerina service attached to an ftp:Listener. It monitors a configured directory on the remote server using the @ftp:ServiceConfig annotation and implements one callback to handle file events. Choose the callback that matches the format you want to receive file content in.

Callback signatures

note

fileInfo and caller are independently optional in the declaration. Valid onFile shapes include (content), (content, fileInfo), (content, caller), and (content, fileInfo, caller). When both fileInfo and caller are declared, they must appear in that order. The compiler plugin rejects other orderings.

FunctionSignatureDescription
onFileremote function onFile(byte[]|stream<byte[], error?> content, ftp:FileInfo fileInfo, ftp:Caller caller) returns error?Invoked for each new file detected in a polling cycle. Content is delivered as a byte[] for in-memory handling, or as stream<byte[], error?> for streaming large files. fileInfo and caller are both optional.
onFileTextremote function onFileText(string content, ftp:FileInfo fileInfo, ftp:Caller caller) returns error?Invoked for each new file detected in a polling cycle, delivering content as a string. fileInfo and caller are both optional.
onFileJsonremote function onFileJson(json|record content, ftp:FileInfo fileInfo, ftp:Caller caller) returns error?Invoked for each new file detected in a polling cycle. Content is delivered as a json value or bound to a user-defined record type. fileInfo and caller are both optional.
onFileXmlremote function onFileXml(xml|record content, ftp:FileInfo fileInfo, ftp:Caller caller) returns error?Invoked for each new file detected in a polling cycle. Content is delivered as an xml value or bound to a user-defined record type. fileInfo and caller are both optional.
onFileCsvremote function onFileCsv(string[][]|record []|stream<string[], error?>|stream<record , error?> content, ftp:FileInfo fileInfo, ftp:Caller caller) returns error?Invoked for each new CSV file detected in a polling cycle. Content can be delivered as string[][], record[], or as a stream of either. Pick the array form for small files and the stream form for large datasets. fileInfo and caller are both optional.
onFileDeleteremote function onFileDelete(string deletedFile, ftp:Caller caller) returns error?Invoked once per file detected as deleted in a polling cycle, receiving the deleted file's path. caller is optional.
onErrorremote function onError(ftp:Error err, ftp:Caller caller) returns error?Invoked when the runtime cannot bind a file's content to the typed parameter of a format-specific handler. For example, an onFileJson handler receiving malformed JSON. caller is optional.
note

The | in the content parameter lists the supported alternative types. The parameter should only be decalred with one of them. For example, onFile can be declared with byte[] or stream<byte[], error?>, not both at once.

Multiple format-specific handlers (onFile, onFileText, onFileJson, onFileXml, onFileCsv) can coexist on the same service to route different file types to different methods using @ftp:FunctionConfig's fileNamePattern. onFileDelete and onErrorcan be added alongside any of them.

Full usage example

import ballerina/ftp;
import ballerina/log;

configurable string host = ?;
configurable int port = ?;
configurable string username = ?;
configurable string password = ?;

listener ftp:Listener sftpListener = check new (
protocol = ftp:SFTP,
host = host,
port = port,
auth = {
credentials: {
username: username,
password: password
}
},
pollingInterval = 10.0
);

@ftp:ServiceConfig {
path: "/home/user/incoming"
}
service "FileProcessor" on sftpListener {

@ftp:FunctionConfig {
fileNamePattern: ".*\\.csv",
afterProcess: ftp:DELETE
}
remote function onFileCsv(stream<string[], error?> csvStream, ftp:FileInfo fileInfo)
returns error? {
log:printInfo("Processing CSV: " + fileInfo.name);
check from string[] row in csvStream
do {
log:printInfo("Row: " + row.toString());
};
}

@ftp:FunctionConfig {
fileNamePattern: ".*\\.json"
}
remote function onFileJson(json content, ftp:FileInfo fileInfo, ftp:Caller caller)
returns error? {
log:printInfo("Processing JSON: " + fileInfo.name);
check caller->move(fileInfo.pathDecoded,
"/home/user/archive/" + fileInfo.name);
}

remote function onFileDelete(string deletedFile) returns error? {
log:printInfo("File deleted: " + deletedFile);
}

remote function onError(ftp:Error err) returns error? {
log:printError("Failed to process file", 'error = err);
}
}
note

Use the @ftp:ServiceConfig annotation to specify the path to monitor and an optional fileNamePattern regex to filter files. You can also use @ftp:FunctionConfig on individual callbacks to set per-function file patterns and post-processing actions (afterProcess and afterError, which can be MOVE or DELETE).

Post-processing for onError

Declaring onError overrides the content method's afterError action. Only @ftp:FunctionConfig annotations on onError itself are honoured. To quarantine files that fail binding, set both afterProcess (runs when onError returns successfully) and afterError (runs if onError itself returns an error):

@ftp:FunctionConfig {                                 
afterProcess: { moveTo: "/home/user/quarantine" },
afterError: { moveTo: "/home/user/quarantine" }
}
remote function onError(ftp:Error err) returns error? {
log:printError("Could not parse file; quarantining", 'error = err);
}

If onError is not declared, the runtime falls back to the content method's afterError action. So simple cases can configure quarantine on onFileJson / onFileCsv directly without an onError handler.


Supporting types

WatchEvent

FieldTypeDescription
addedFilesFileInfo[]Array of metadata records for files that were added since the last poll.
deletedFilesstring[]Array of file paths that were deleted since the last poll.

FileInfo

FieldTypeDescription
pathstringThe relative path of the file on the remote server.
pathDecodedstringNormalized absolute path within the file system. Prefer this over path when passing to ftp:Caller operations.
namestringThe file name (without path).
sizeintThe file size in bytes.
fileTypestringMIME type or file classification reported by the underlying VFS.
depthintDirectory nesting level within the file system.
lastModifiedTimestampintThe Unix timestamp (milliseconds) of the last modification.
isFolderbooleantrue if the entry is a directory.
isFilebooleantrue if the entry is a regular file.
isReadablebooleantrue if the file is readable.
isWritablebooleantrue if the file is writable.
isExecutablebooleantrue if the file is executable.
isHiddenbooleantrue if the file is hidden.
extensionstringThe file extension.
uristringRaw URI of the file as reported by the underlying VFS.
publicURIStringstringPublic-display URI of the file (suitable for logging or external display).
friendlyURIstringHuman-readable URI with authentication details stripped.
rootURIstringURI of the root of the file system the file belongs to.
schemestringURI scheme (for example, ftp, sftp, ftps).

AuthConfiguration

FieldTypeDescription
credentialsCredentialsUsername and password credentials for authentication.
privateKeyPrivateKeySSH private key configuration for SFTP authentication.
secureSocketSecureSocketSSL/TLS configuration for FTPS connections.
preferredMethodsPreferredMethod[]Preferred authentication methods in order of priority (default: [PUBLICKEY, PASSWORD]).

Credentials

FieldTypeDescription
usernamestringThe username for authentication.
passwordstringThe password for authentication. Optional, omit when authenticating with a private key only.

PrivateKey

FieldTypeDescription
pathstringPath to the SSH private key file.
passwordstringPassphrase for the private key. Optional, omit if the key is unencrypted.