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:
| Component | Role |
|---|---|
ftp:Listener | Polls a remote FTP/SFTP directory at a configurable interval and detects new or deleted files. |
ftp:Service | Hosts 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:Caller | An FTP client passed to callbacks, enabling additional file operations (read, write, move, delete) within the handler. |
ftp:FileInfo | Metadata 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 Type | Description |
|---|---|
ListenerConfiguration | Configuration for the FTP/SFTP listener including connection details, authentication, and polling settings. |
ListenerConfiguration fields:
| Field | Type | Default | Description |
|---|---|---|---|
protocol | Protocol | FTP | The file transfer protocol to use (FTP, FTPS, or SFTP). |
host | string | "127.0.0.1" | Hostname or IP address of the FTP server. |
port | int | 21 | Port number of the FTP server. Typically 21 for FTP and FTPS explicit, and 990 for FTPS implicit. |
auth | AuthConfiguration | () | Authentication settings, including credentials, SSH private key (SFTP), SSL/TLS configuration (FTPS), and preferred SFTP authentication methods. |
pollingInterval | decimal | 60.0 | Interval in seconds between directory polls. |
userDirIsRoot | boolean | false | Whether to treat the user's home directory as the root directory. |
laxDataBinding | boolean | false | When true, enables relaxed data binding for JSON/XML: null values map to optional fields and missing fields map to null values. |
connectTimeout | decimal | 30.0 | Connection timeout in seconds. |
socketConfig | SocketConfig | () | Per-protocol socket timeouts: ftpDataTimeout (FTP data), ftpSocketTimeout (FTP control), and sftpSessionTimeout (SFTP session). |
fileTransferMode | FileTransferMode | BINARY | File transfer mode (BINARY or ASCII). |
retryConfig | RetryConfig | () | 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. |
proxy | ProxyConfiguration | () | Proxy / jump-host configuration (SFTP only). |
sftpCompression | TransferCompression[] | [NO] | Compression algorithms to negotiate (ZLIB, ZLIBOPENSSH, NO) (SFTP only). |
sftpSshKnownHosts | string | () | Path to the SSH known_hosts file used for host key verification (SFTP only). |
csvFailSafe | FailSafeOptions | () | 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. |
coordination | CoordinationConfig | () | Distributed task coordination. When set, multiple listener members coordinate so that only one polls at a time and the others act as warm standby. |
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
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.
| Function | Signature | Description |
|---|---|---|
onFile | remote 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. |
onFileText | remote 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. |
onFileJson | remote 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. |
onFileXml | remote 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. |
onFileCsv | remote 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. |
onFileDelete | remote 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. |
onError | remote 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. |
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);
}
}
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
| Field | Type | Description |
|---|---|---|
addedFiles | FileInfo[] | Array of metadata records for files that were added since the last poll. |
deletedFiles | string[] | Array of file paths that were deleted since the last poll. |
FileInfo
| Field | Type | Description |
|---|---|---|
path | string | The relative path of the file on the remote server. |
pathDecoded | string | Normalized absolute path within the file system. Prefer this over path when passing to ftp:Caller operations. |
name | string | The file name (without path). |
size | int | The file size in bytes. |
fileType | string | MIME type or file classification reported by the underlying VFS. |
depth | int | Directory nesting level within the file system. |
lastModifiedTimestamp | int | The Unix timestamp (milliseconds) of the last modification. |
isFolder | boolean | true if the entry is a directory. |
isFile | boolean | true if the entry is a regular file. |
isReadable | boolean | true if the file is readable. |
isWritable | boolean | true if the file is writable. |
isExecutable | boolean | true if the file is executable. |
isHidden | boolean | true if the file is hidden. |
extension | string | The file extension. |
uri | string | Raw URI of the file as reported by the underlying VFS. |
publicURIString | string | Public-display URI of the file (suitable for logging or external display). |
friendlyURI | string | Human-readable URI with authentication details stripped. |
rootURI | string | URI of the root of the file system the file belongs to. |
scheme | string | URI scheme (for example, ftp, sftp, ftps). |
AuthConfiguration
| Field | Type | Description |
|---|---|---|
credentials | Credentials | Username and password credentials for authentication. |
privateKey | PrivateKey | SSH private key configuration for SFTP authentication. |
secureSocket | SecureSocket | SSL/TLS configuration for FTPS connections. |
preferredMethods | PreferredMethod[] | Preferred authentication methods in order of priority (default: [PUBLICKEY, PASSWORD]). |
Credentials
| Field | Type | Description |
|---|---|---|
username | string | The username for authentication. |
password | string | The password for authentication. Optional, omit when authenticating with a private key only. |
PrivateKey
| Field | Type | Description |
|---|---|---|
path | string | Path to the SSH private key file. |
password | string | Passphrase for the private key. Optional, omit if the key is unencrypted. |