Skip to main content

Overview

The FTPClient class provides a complete FTP client implementation designed specifically for Cloudflare Workers. It supports standard FTP operations including file transfers, directory management, and secure connections via STARTTLS.

Constructor

constructor(
  readonly host: string,
  opts?: ConnectionOptions
)
host
string
required
The hostname or IP address of the FTP server you want to connect to.
opts
ConnectionOptions
Optional connection configuration. See ConnectionOptions for all available options.

Example

import { FTPClient } from 'workerd-ftp';

const client = new FTPClient('ftp.example.com', {
  user: 'myuser',
  pass: 'mypassword',
  port: 21,
  secure: true
});

Properties

host
string
The FTP server hostname or IP address (readonly).

Connection Methods

connect()

Initializes the connection to the FTP server.
public async connect(): Promise<void>
This method performs the following operations:
  1. Establishes a TCP connection to the server
  2. Waits for the server hello message
  3. Discovers server features via the FEAT command
  4. Optionally performs STARTTLS handshake if secure is enabled
  5. Authenticates with provided credentials
  6. Switches to binary transfer mode
You must call connect() before performing any FTP operations.
Example:
const client = new FTPClient('ftp.example.com');
await client.connect();

close()

Closes all active connections to the FTP server.
public async close(): Promise<void>
Always call close() when you’re done to avoid loose connections and resource leaks.
Example:
try {
  await client.connect();
  // ... perform operations ...
} finally {
  await client.close();
}

Directory Navigation

cwd()

Returns the current working directory (equivalent to pwd).
public async cwd(): Promise<string>
Returns: The absolute path of the current working directory. Example:
const currentDir = await client.cwd();
console.log(`Current directory: ${currentDir}`);

chdir()

Changes the current directory (equivalent to cd).
public async chdir(path: string): Promise<void>
path
string
required
The directory path to change to.
Example:
await client.chdir('/public_html');

cdup()

Moves to the parent directory (equivalent to cd ..).
public async cdup(): Promise<void>
Example:
await client.cdup();

File Transfer Methods

download()

Downloads a file from the server and returns it as a Uint8Array.
public async download(fileName: string): Promise<Uint8Array>
fileName
string
required
The name or path of the file to download.
Returns: The file contents as a Uint8Array. Example:
const fileData = await client.download('document.pdf');

downloadReadable()

Downloads a file using a ReadableStream interface for streaming large files.
public async downloadReadable(
  fileName: string
): Promise<ReadableStream<Uint8Array>>
fileName
string
required
The name or path of the file to download.
Returns: A ReadableStream for the file contents.
You must call finalizeStream() after consuming the stream to release the lock and clean up resources. Alternatively, you can use the AsyncDisposable interface.
Example:
const stream = await client.downloadReadable('large-file.zip');
const reader = stream.getReader();

try {
  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    // Process chunk...
  }
} finally {
  reader.releaseLock();
  await client.finalizeStream();
}

upload()

Uploads a file to the server.
public async upload(fileName: string, data: Uint8Array): Promise<void>
fileName
string
required
The name or path where the file should be stored on the server.
data
Uint8Array
required
The file contents to upload.
Example:
const data = new TextEncoder().encode('Hello, FTP!');
await client.upload('greeting.txt', data);

uploadWritable()

Uploads a file using a WritableStream interface for streaming large files.
public async uploadWritable(
  fileName: string,
  allocate?: number
): Promise<WritableStream<Uint8Array>>
fileName
string
required
The name or path where the file should be stored on the server.
allocate
number
Number of bytes to allocate for the file. Some servers require this parameter.
Returns: A WritableStream for uploading file contents.
You must call finalizeStream() after closing the writer to release the lock and clean up resources. Alternatively, you can use the AsyncDisposable interface.
Example:
const writable = await client.uploadWritable('output.txt', 1024);
const writer = writable.getWriter();

try {
  await writer.write(new TextEncoder().encode('Line 1\n'));
  await writer.write(new TextEncoder().encode('Line 2\n'));
  await writer.close();
} finally {
  await client.finalizeStream();
}

finalizeStream()

Unlocks and closes connections for streaming operations.
public async finalizeStream(): Promise<void>
This method must be called after using downloadReadable() or uploadWritable() to properly clean up resources.

File Information Methods

stat()

Retrieves detailed file information from the FTP server.
public async stat(filename: string): Promise<FTPFileInfo>
filename
string
required
The name or path of the file to query.
Returns: A FTPFileInfo object containing file metadata. Example:
const info = await client.stat('document.pdf');
console.log(`File size: ${info.size} bytes`);
console.log(`Last modified: ${info.mtime}`);
console.log(`Is directory: ${info.isDirectory}`);

size()

Returns the file size in bytes.
public async size(filename: string): Promise<number>
filename
string
required
The name or path of the file.
Returns: File size in bytes. Example:
const bytes = await client.size('archive.zip');
console.log(`File is ${bytes} bytes`);

modified()

Returns the file’s last modification time.
public async modified(filename: string): Promise<Date>
filename
string
required
The name or path of the file.
Returns: A Date object representing the last modification time.
This method throws an error if the server doesn’t support the MDTM feature.
Example:
const modTime = await client.modified('data.json');
console.log(`Last modified: ${modTime.toISOString()}`);

File Operations

rename()

Renames a file on the server.
public async rename(from: string, to: string): Promise<boolean>
from
string
required
The current filename or path.
to
string
required
The new filename or path.
Returns: true on success. Example:
await client.rename('old-name.txt', 'new-name.txt');

rm()

Deletes a file from the server.
public async rm(fileName: string): Promise<void>
fileName
string
required
The name or path of the file to delete.
Example:
await client.rm('temporary-file.txt');

Directory Operations

mkdir()

Creates a directory on the server.
public async mkdir(dirName: string): Promise<boolean>
dirName
string
required
The name or path of the directory to create.
Returns: true on success. Example:
await client.mkdir('new-folder');

rmdir()

Removes a directory from the server.
public async rmdir(dirName: string): Promise<void>
dirName
string
required
The name or path of the directory to remove.
The directory must be empty before it can be removed.
Example:
await client.rmdir('old-folder');

Directory Listing Methods

list()

Retrieves a basic directory listing from the server.
public async list(dirName?: string): Promise<string[]>
dirName
string
The directory to list. Defaults to the current working directory if not specified.
Returns: An array of strings, each representing a file or directory entry. Example:
const files = await client.list();
files.forEach(file => console.log(file));

extendedList()

Retrieves a detailed directory listing with file metadata.
public async extendedList(dirName?: string): Promise<Array<[string, FTPFileInfo]>>
dirName
string
The directory to list. Defaults to the current working directory if not specified.
Returns: An array of tuples, where each tuple contains:
  • [0]: The filename (string)
  • [1]: A FTPFileInfo object with metadata
Example:
const entries = await client.extendedList('/public_html');
for (const [name, info] of entries) {
  console.log(`${name}: ${info.size} bytes, modified ${info.mtime}`);
}

Build docs developers (and LLMs) love