molex-ftp
v2.3.1
Published
Lightweight FTP client using native Node.js TCP sockets (net module) with zero dependencies
Maintainers
Readme
molex-ftp-npm
Lightweight FTP client built with native Node.js TCP sockets. Zero dependencies, optimized for performance.
Features
- Zero dependencies - Uses only native Node.js modules
- Promise-based API - Modern async/await support
- Streaming support - Memory-efficient downloads for large files
- Full FTP support - Upload, download, list, delete, rename, chmod, stat, and more
- Debug mode - See all FTP commands and responses in real-time
Installation
npm install molex-ftpQuick Start
const FTPClient = require('molex-ftp');
const client = new FTPClient();
await client.connect({
host: 'ftp.example.com',
user: 'username',
password: 'password'
});
// Upload content (string or Buffer)
await client.upload('Hello World!', '/path/to/file.txt', true);
// Upload local file to FTP server
await client.uploadFile('./local.txt', '/remote/file.txt');
// Download to memory
const data = await client.download('/path/to/file.txt');
console.log(data.toString());
// Download to local file
await client.downloadFile('/remote/file.txt', './local.txt');
await client.close();Constructor Options
const client = new FTPClient({
debug: false, // Enable debug logging
timeout: 30000, // Command timeout in milliseconds (default: 30000)
logger: console.log // Custom logger function
});API Reference
Connection Methods
connect(options)
await client.connect({
host: 'ftp.example.com', // Required
port: 21, // Default: 21
user: 'username', // Default: 'anonymous'
password: 'password' // Default: 'anonymous@'
});close()
await client.close();File Methods
upload(data, remotePath, ensureDir)
await client.upload('content', '/path/file.txt'); // Basic upload
await client.upload(buffer, '/path/file.bin'); // Upload Buffer
await client.upload('content', '/deep/path/file.txt', true); // Auto-create parent dirsuploadFile(localPath, remotePath, ensureDir)
Upload local file from disk to FTP server.
await client.uploadFile('./local.txt', '/remote/file.txt'); // Upload local file
await client.uploadFile('./docs/report.pdf', '/reports/2026.pdf'); // Auto-creates parent dirsdownload(remotePath) → Buffer
Download file into memory as a Buffer.
const data = await client.download('/path/file.txt');
console.log(data.toString());downloadFile(remotePath, localPath) → number
Download file from FTP server to local disk.
const bytes = await client.downloadFile('/backup.zip', './local-backup.zip');
console.log(`Downloaded ${bytes} bytes`);downloadStream(remotePath, writeStream) → number
Stream download directly to a writable stream (for custom processing).
const fs = require('fs');
const fileStream = fs.createWriteStream('./local-file.bin');
const bytes = await client.downloadStream('/remote.bin', fileStream);
console.log(`Saved ${bytes} bytes to disk`);delete(path)
await client.delete('/path/file.txt');removeDir(path, recursive)
Remove directory, optionally with all contents.
await client.removeDir('/path/emptydir'); // Remove empty directory
await client.removeDir('/path/dir', true); // Delete recursively with contentsrename(from, to)
await client.rename('/old.txt', '/new.txt');exists(path) → boolean
const exists = await client.exists('/path/file.txt');stat(path) → Object
Get detailed file/directory information.
const info = await client.stat('/path/file.txt');
// { exists: true, size: 1024, isFile: true, isDirectory: false }size(path) → number
const bytes = await client.size('/path/file.txt');modifiedTime(path) → Date
const date = await client.modifiedTime('/path/file.txt');chmod(path, mode)
Change file permissions (Unix/Linux servers only).
await client.chmod('/path/file.txt', '755'); // String format
await client.chmod('/path/script.sh', 0755); // Octal formatDirectory Methods
list(path) → string
Raw directory listing.
const listing = await client.list('/path');listDetailed(path) → Array
Parsed directory listing with permissions, owner, size, etc.
const files = await client.listDetailed('/path');
// [
// { name: 'file.txt', type: 'file', permissions: '-rw-r--r--',
// owner: 'user', group: 'group', size: 1024, date: 'Jan 15 10:30' },
// { name: 'subdir', type: 'directory', permissions: 'drwxr-xr-x', ... }
// ]mkdir(path)
await client.mkdir('/path/newdir');cd(path)
await client.cd('/path/to/directory');pwd() → string
const currentDir = await client.pwd();ensureDir(path, recursive)
Create directory if it doesn't exist. Auto-detects file paths (with extensions) and creates parent directory.
await client.ensureDir('/deep/nested/path'); // Create directory path
await client.ensureDir('/path/to/file.txt'); // Auto-detects file, creates /path/to/
await client.ensureDir('/single', false); // Non-recursive, parent must existUtility Methods
getState() → Object
Get current client state for debugging.
const state = client.getState();
// {
// connected: true,
// authenticated: true,
// host: 'ftp.example.com',
// ...
// }setDebug(enabled)
Toggle debug mode at runtime.
client.setDebug(true);site(command) → Object
Execute server-specific SITE commands.
await client.site('CHMOD 755 /path/file.txt'); // Alternative chmod
const response = await client.site('HELP'); // Get server helpEvents
client.on('connected', () => console.log('TCP connection established'));
client.on('response', (line) => console.log('FTP:', line));
client.on('error', (err) => console.error('Error:', err));
client.on('close', () => console.log('Connection closed'));Debugging
Enable debug mode to see all FTP commands and responses:
const client = new FTPClient({ debug: true });
await client.connect({ host: 'ftp.example.com', user: 'user', password: 'pass' });
// [FTP Debug] Connecting to ftp.example.com:21 as user
// [FTP Debug] TCP connection established
// [FTP Debug] <<< 220 Welcome to FTP server
// [FTP Debug] >>> USER user
// [FTP Debug] <<< 331 Password required
// [FTP Debug] >>> PASS ********
// [FTP Debug] <<< 230 Login successfulPerformance
TCP optimizations are automatically applied:
- TCP_NODELAY - Disables Nagle's algorithm for lower latency
- Keep-alive - Detects dead connections (10s interval)
Typical transfer speeds: ~2.5 MB/s for 1MB files over standard internet connections.
For large files, use downloadFile() or downloadStream() to save directly to disk without buffering in memory:
// Download directly to disk (recommended for large files)
const bytes = await client.downloadFile('/backup.zip', './local-backup.zip');
console.log(`Saved ${bytes} bytes`);
// Or use downloadStream for custom processing
const fs = require('fs');
const fileStream = fs.createWriteStream('./large-backup.zip');
const bytes = await client.downloadStream('/backup.zip', fileStream);
console.log(`Saved ${bytes} bytes to disk`);Error Handling
try {
await client.upload('data', '/readonly/file.txt');
} catch (err) {
if (err.message.includes('FTP Error 550')) {
console.error('Permission denied');
}
}Example
const FTPClient = require('molex-ftp');
async function main() {
const client = new FTPClient({ debug: true });
try {
await client.connect({
host: 'ftp.example.com',
user: 'admin',
password: 'secret'
});
// Check file info
const info = await client.stat('/backup/data.json');
if (info.exists) {
console.log(`File size: ${info.size} bytes`);
const data = await client.download('/backup/data.json');
console.log('Downloaded:', data.toString());
}
// Upload new file
await client.upload('new data', '/backup/updated.json', true);
await client.close();
} catch (err) {
console.error('FTP Error:', err.message);
}
}
main();License
ISC License
