TFTP Client and Server
This module provides a full-featured streaming TFTP (Trivial File Transfer Protocol) client and server for Node.js. It supports several TFTP RFCs (1350, 2347, 2348, 2349, 3617, 7440) and de facto extensions like rollover and windowsize, which address TFTP's inherent 32MB file size limit and slow lock-step transfer mechanism. The current stable version is 0.1.2. Developed for Node.js versions 0.10 and newer, it integrates with Node.js streams for easy file transfers. However, the README clearly states that TFTP is an obsolete legacy protocol, generally unsuitable for internet transfers due to UDP packet loss, and recommends FTP for most use cases. Its primary differentiation is providing a complete TFTP solution within Node.js, including performance-boosting extensions, despite the protocol's limitations. The package does not appear to have an active release cadence, with the last known update being in 2015.
Common errors
-
Error: bind EADDRINUSE :::69
cause The default TFTP server port (UDP 69) is already in use by another process on the system, or the server was not properly shut down from a previous run.fixIdentify and stop the conflicting process, or configure the TFTP server to listen on a different, available port using the `server.listen(PORT)` method. -
Error: Client GET error: File not found
cause The requested file does not exist on the TFTP server at the specified path, or the server lacks read permissions for that file.fixVerify that the file path requested by the client is correct and that the file exists on the server. Ensure the server process has read access to the file and its containing directory. -
TypeError: tftp.createClient is not a function
cause This error typically occurs if the module is imported using ES module syntax (`import`) instead of CommonJS `require()`, or if the module's main export structure has been misunderstood.fixEnsure you are importing the module using `const tftp = require('tftp');` and then accessing `tftp.createClient()` or `tftp.createServer()`.
Warnings
- gotcha TFTP is an obsolete legacy protocol built on UDP. It is highly susceptible to packet loss and is explicitly not recommended for use over the internet. FTP or other robust protocols should be used instead for remote file transfers.
- gotcha On Windows platforms, there's a known issue with UDP packet buffering that can lead to dropped packets, especially when using TFTP's 'windowsize' option larger than 6 blocks. This can severely degrade transfer reliability and potentially cause failures.
- gotcha Without specific TFTP extensions (like blocksize, rollover, or windowsize), the original RFC 1350 limits file transfers to 32MB. Even with extensions, performance is inherently slow due to the lock-step (one acknowledgement per packet) nature of the protocol.
- breaking The package's core TFTP functionality operates over UDP port 69 by default. Deploying this server requires appropriate network configuration (e.g., firewall rules) to allow UDP traffic on this port. Conflicting services or insufficient permissions can prevent the server from binding.
Install
-
npm install tftp -
yarn add tftp -
pnpm add tftp
Imports
- TFTP client instantiation
import { createClient } from 'tftp'; // Incorrect for CommonJS module const client = createClient();const tftp = require('tftp'); const client = tftp.createClient(); - TFTP server instantiation
import tftp from 'tftp'; const server = tftp.createServer(); // Incorrect if 'tftp' is not the default export containing 'createServer'
const tftp = require('tftp'); const server = tftp.createServer(); - TFTP client GET operation
const { get } = require('tftp').createClient(); // 'get' is a method on the client instance, not a named export.const tftp = require('tftp'); const client = tftp.createClient(); const get = client.get('remoteFile.txt', { remoteAddress: '127.0.0.1', remotePort: 69 }); get.on('error', (err) => console.error('GET error:', err)); get.on('timeout', () => console.error('GET timeout.'));
Quickstart
const tftp = require('tftp');
const fs = require('fs');
// --- TFTP Server Example ---
const server = tftp.createServer();
server.on('error', (err) => {
console.error('Server error:', err.message);
});
server.on('get', (req, respond) => {
console.log(`Server received GET request for: ${req.file} from ${req.remoteAddress}:${req.remotePort}`);
const filePath = `./server_files/${req.file}`;
fs.access(filePath, fs.constants.F_OK, (err) => {
if (err) {
console.error(`File not found: ${filePath}`);
return req.error('File not found');
}
respond(fs.createReadStream(filePath));
});
});
server.on('put', (req, readStream) => {
console.log(`Server received PUT request for: ${req.file} from ${req.remoteAddress}:${req.remotePort}`);
const filePath = `./server_files/${req.file}`;
const writeStream = fs.createWriteStream(filePath);
readStream.pipe(writeStream);
readStream.on('end', () => {
console.log(`File ${req.file} saved on server.`);
});
readStream.on('error', (err) => {
console.error(`Error saving file ${req.file} on server:`, err.message);
});
});
server.listen(69, () => {
console.log('TFTP server listening on port 69...');
});
// --- TFTP Client Example (after server is running) ---
// Ensure 'test_file.txt' exists in a 'client_files' directory or similar for PUT
// Ensure 'server_files/remote_file.txt' exists for GET
// To run this example:
// 1. Create a directory named 'server_files'
// 2. Place a file named 'remote_file.txt' inside 'server_files'
// 3. Create a directory named 'client_downloads'
const client = tftp.createClient();
const remoteHost = '127.0.0.1';
// Client GET operation
const getRequest = client.get('remote_file.txt', { remoteAddress: remoteHost, remotePort: 69 });
const downloadPath = './client_downloads/downloaded_file.txt';
const writeStream = fs.createWriteStream(downloadPath);
getRequest.on('error', (err) => {
console.error('Client GET error:', err.message);
process.exit(1);
});
getRequest.on('timeout', () => {
console.error('Client GET timed out.');
process.exit(1);
});
getRequest.on('end', () => {
console.log(`File downloaded to ${downloadPath}`);
});
getRequest.pipe(writeStream);
// // Client PUT operation (uncomment to test PUT)
// const uploadPath = './client_files/upload_me.txt'; // Make sure this file exists
// const putRequest = client.put('uploaded_file.txt', { remoteAddress: remoteHost, remotePort: 69 });
// const readStream = fs.createReadStream(uploadPath);
// putRequest.on('error', (err) => {
// console.error('Client PUT error:', err.message);
// process.exit(1);
// });
// putRequest.on('timeout', () => {
// console.error('Client PUT timed out.');
// process.exit(1);
// });
// putRequest.on('end', () => {
// console.log(`File uploaded from ${uploadPath}`);
// });
// readStream.pipe(putRequest);