Build a Simple File Compressor with Node.js in 10 Minutes


Introduction
Have you ever wondered how file compression works behind the scenes? In this beginner-friendly tutorial, I'll show you how to build a simple command-line tool with Node.js that can compress and decompress files in just 10 minutes! We'll explore Node's powerful streams without getting overwhelmed by complex details.
What You'll Need
Node.js is installed on your computer
Basic JavaScript knowledge
A text editor or IDE
10 minutes of your time!
Project Setup
First, let's create a new folder and set up our project:
mkdir file-compressor
cd file-compressor
npm init -y
npm install readline-sync
We're using just one external package readline-sync
to make it easier to get user input from the command line.
The Code: Step by Step
Let's build our file compressor piece by piece:
Step 1: Import the Dependencies
Create a file called index.js
and add these imports:
// Import the modules we need
const fs = require('fs'); // For working with files
const zlib = require('zlib'); // For compression
const path = require('path'); // For handling file paths
const readlineSync = require('readline-sync'); // For user input
// Show a welcome message
console.log('==== File Compressor ====');
Step 2: Create a Menu Interface
// Ask the user what they want to do
const choice = readlineSync.question('Do you want to (c)ompress or (d)ecompress a file? ');
if (choice.toLowerCase() === 'c') {
compressFile();
} else if (choice.toLowerCase() === 'd') {
decompressFile();
} else {
console.log('Invalid choice. Please enter "c" or "d".');
}
Step 3: Implement the Compression Function
function compressFile() {
// Ask for the file to compress
const inputPath = readlineSync.question('Enter the path of the file to compress: ');
// Check if the file exists
if (!fs.existsSync(inputPath)) {
console.log('That file doesn\'t exist. Please check the path and try again.');
return;
}
// Create output filename
const outputPath = inputPath + '.gz';
console.log('Starting compression...');
// Set up our file processing pipeline
const readStream = fs.createReadStream(inputPath);
const writeStream = fs.createWriteStream(outputPath);
const gzip = zlib.createGzip();
// Connect everything together
readStream
.pipe(gzip)
.pipe(writeStream)
.on('finish', () => {
// Show results when done
const originalSize = fs.statSync(inputPath).size;
const compressedSize = fs.statSync(outputPath).size;
const percentage = ((1 - compressedSize / originalSize) * 100).toFixed(2);
console.log('\nCompression complete!');
console.log(`Original size: ${formatSize(originalSize)}`);
console.log(`Compressed size: ${formatSize(compressedSize)}`);
console.log(`You saved: ${percentage}% of space`);
})
.on('error', (err) => {
console.log('Something went wrong:', err.message);
});
}
Step 4: Implement the Decompression Function
function decompressFile() {
// Ask for the file to decompress
const inputPath = readlineSync.question('Enter the path of the compressed file: ');
// Check if the file exists
if (!fs.existsSync(inputPath)) {
console.log('That file doesn\'t exist. Please check the path and try again.');
return;
}
// Create output filename (remove .gz if present)
let outputPath = inputPath.endsWith('.gz')
? inputPath.slice(0, -3)
: inputPath + '.decompressed';
console.log('Starting decompression...');
// Set up our file processing pipeline
const readStream = fs.createReadStream(inputPath);
const writeStream = fs.createWriteStream(outputPath);
const gunzip = zlib.createGunzip();
// Connect everything together
readStream
.pipe(gunzip)
.pipe(writeStream)
.on('finish', () => {
console.log('\nDecompression complete!');
console.log(`Output file: ${outputPath}`);
})
.on('error', (err) => {
console.log('Something went wrong:', err.message);
console.log('This might not be a valid compressed file.');
});
}
Step 5: Add a Helper Function for Formatting File Sizes
// Helper function to format file sizes
function formatSize(bytes) {
if (bytes < 1024) {
return bytes + ' bytes';
} else if (bytes < 1024 * 1024) {
return (bytes / 1024).toFixed(2) + ' KB';
} else {
return (bytes / (1024 * 1024)).toFixed(2) + ' MB';
}
}
How to Run Your File Compressor
Save your code and run it from the terminal with:
node index.js
Follow the prompts to compress or decompress a file. Try compressing a text file first - you'll be amazed at how much smaller it gets!
Understanding Streams: The Key Concept
The magic of this program is in this simple line:
readStream.pipe(gzip).pipe(writeStream)
This creates a pipeline where:
readStream
reads your file bit by bitEach bit flows through
gzip
which compresses itThe compressed bits flow to
writeStream
which saves them
Think of it like a water pipe system. The beauty is that you can process files of any size because you're only handling small pieces at a time. This is why Node.js is so powerful for file operations!
Troubleshooting Common Issues
"File not found" error: Make sure you type the full path to your file
Nothing happens after starting compression: Large files take time to process, be patient
The decompressed file doesn't work: Make sure you're decompressing a proper gzip file
Error messages during decompression: The input file may not be a valid gzip file
What You've Learned
In just a few minutes, you've:
Created a useful command-line tool
Learned about Node.js streams
Used the built-in compression library
Processed files efficiently
Now you understand one of the most powerful patterns in Node.js! This same approach works for many other types of file processing tasks.
Next Steps to Enhance Your Compressor
Once you're comfortable with this code, try:
Adding a progress indicator
Compressing entire folders
Supporting different compression levels
Creating a simple GUI interface with Electron
Conclusion
File compression is a fascinating topic, and Node.js makes it remarkably straightforward to implement. The streams API is one of Node's most powerful features, allowing you to process data efficiently without loading everything into memory at once.
I hope you enjoyed building this simple file compressor! Let me know in the comments if you have any questions or ideas for improving it.
If you found this tutorial helpful, don't forget to like and share it with fellow developers! Also, follow me for more Node.js tutorials and web development content.
Happy coding!
Subscribe to my newsletter
Read articles from Abigeal Afolabi directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Abigeal Afolabi
Abigeal Afolabi
๐ Software Engineer by day, SRE magician by night! โจ Tech enthusiast with an insatiable curiosity for data. ๐ Harvard CS50 Undergrad igniting my passion for code. Currently delving into the MERN stack โ because who doesn't love crafting seamless experiences from front to back? Join me on this exhilarating journey of embracing technology, penning insightful tech chronicles, and unraveling the mysteries of data! ๐๐ง Let's build, let's write, let's explore โ all aboard the tech express! ๐๐ #CodeAndCuriosity