đ Introduction
In many web applications, users need to download multiple files at once. Instead of sending each file individually, it is more efficient to combine them into a single ZIP archive. Express.js, together with the archiver package, makes it easy to create ZIP files dynamically and stream them directly to the client without permanently storing the archive on the server.
Information
đ Prerequisites
- Node.js installed.
- Express.js installed.
- Basic Express.js server created.
- Multiple files available in a server directory.
đĻ Installing the Required Package
Install the archiver package to create ZIP archives programmatically.
Install archiver
npm install archiverđ Project Structure
đ Creating a ZIP Archive
Import the required modules, create an archive, and stream it directly to the client.
Create and Download ZIP Archive
const express = require('express');
const archiver = require('archiver');
const path = require('path');
const app = express();
app.get('/download-all', (req, res) => {
res.attachment('documents.zip');
const archive = archiver('zip', {
zlib: { level: 9 }
});
archive.pipe(res);
archive.file(
path.join(__dirname, 'downloads', 'report.pdf'),
{ name: 'report.pdf' }
);
archive.file(
path.join(__dirname, 'downloads', 'invoice.xlsx'),
{ name: 'invoice.xlsx' }
);
archive.file(
path.join(__dirname, 'downloads', 'image.png'),
{ name: 'image.png' }
);
archive.finalize();
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});Success
đ Understanding the Code
| Statement | Purpose |
|---|---|
| res.attachment() | Sets the response as a downloadable attachment. |
| archiver('zip') | Creates a new ZIP archive. |
| archive.pipe(res) | Streams the ZIP archive to the client. |
| archive.file() | Adds an existing file to the archive. |
| archive.finalize() | Completes the archive and begins streaming. |
đ Adding an Entire Directory
Instead of adding files individually, you can include an entire directory in the ZIP archive.
Archive a Folder
app.get('/download-folder', (req, res) => {
res.attachment('downloads.zip');
const archive = archiver('zip');
archive.pipe(res);
archive.directory(
path.join(__dirname, 'downloads'),
false
);
archive.finalize();
});The second argument (false) places the folder contents directly in the root of the ZIP archive.
đ Adding Files Dynamically
You can add files dynamically by iterating through a list of filenames.
Dynamic ZIP Creation
const files = [
'report.pdf',
'invoice.xlsx',
'image.png'
];
files.forEach(file => {
archive.file(
path.join(__dirname, 'downloads', file),
{ name: file }
);
});
archive.finalize();â ī¸ Handling Errors
Archive Error Handling
archive.on('error', (err) => {
res.status(500).send(err.message);
});Warning
đ Validating Download Requests
When users choose which files to download, validate every filename before adding it to the archive.
Simple Filename Validation
const allowedFiles = [
'report.pdf',
'invoice.xlsx',
'image.png'
];
if (!allowedFiles.includes(fileName)) {
return res.status(404).send('Invalid file.');
}đ ZIP Download Workflow
đ ZIP Creation Lifecycle
đ Common Archiver Methods
| Method | Purpose |
|---|---|
| archive.file() | Adds a single file to the archive. |
| archive.directory() | Adds an entire directory. |
| archive.append() | Adds custom content or streams. |
| archive.pipe() | Streams the archive to a writable destination. |
| archive.finalize() | Completes archive generation. |
đ Download Individual Files vs ZIP Archive
| Feature | Individual Downloads | ZIP Archive |
|---|---|---|
| Number of Requests | One request per file | Single request |
| User Convenience | Lower | Higher |
| Download Management | Multiple downloads | One archive file |
| Network Efficiency | Less efficient | More efficient for multiple files |
đĄ Best Practices
- Stream ZIP archives directly instead of storing temporary ZIP files.
- Validate filenames before adding them to the archive.
- Use meaningful archive names such as reports.zip or documents.zip.
- Handle archive creation errors gracefully.
- Protect sensitive downloads with authentication and authorization.
- Use compression only when it improves download efficiency.
Best Practice
đ Learn More
Explore the official documentation for creating ZIP archives:
âĸ Express.js Official Documentation
âĸ Archiver Package Documentation
âĸ Node.js Streams Documentation