Implementing File Download in Express.js

🚀 Introduction

Express.js provides an easy way to allow users to download files from the server. Instead of displaying a file in the browser, Express can send it as an attachment so the browser prompts the user to save it. This functionality is commonly used for downloading PDFs, images, ZIP archives, reports, invoices, and other documents.

Information

Express.js provides the res.download() method to send a file as an attachment, automatically setting the appropriate HTTP headers for file downloads.

📋 Prerequisites

  • Node.js installed.
  • Express.js installed.
  • A basic Express.js server created.
  • A file available on the server for downloading.

📁 Project Structure

express-app
downloads
index.js
package.json
sample.pdf
report.xlsx
image.png

📌 Using res.download()

The res.download() method sends a file to the client and instructs the browser to download it instead of displaying it.

Basic File Download

const express = require('express');
const path = require('path');

const app = express();

app.get('/download', (req, res) => {
  const filePath = path.join(__dirname, 'downloads', 'sample.pdf');

  res.download(filePath);
});

app.listen(3000, () => {
  console.log('Server running on http://localhost:3000');
});

Visiting http://localhost:3000/download prompts the browser to download sample.pdf.

Success

If the requested file exists and is accessible, the browser automatically starts the download.

📌 Downloading with a Custom File Name

You can specify a custom filename that users will see when saving the file.

Custom Download Name

app.get('/download-report', (req, res) => {
  const filePath = path.join(__dirname, 'downloads', 'report.xlsx');

  res.download(filePath, 'Monthly-Report.xlsx');
});

Although the original file is named report.xlsx, the browser downloads it as Monthly-Report.xlsx.

📌 Handling Download Errors

Always handle errors to avoid unexpected application behavior when the requested file does not exist or cannot be accessed.

Error Handling

app.get('/download', (req, res) => {
  const filePath = path.join(__dirname, 'downloads', 'sample.pdf');

  res.download(filePath, (err) => {
    if (err) {
      res.status(404).send('File not found.');
    }
  });
});

Warning

Always verify that the file exists before attempting to download it, especially when the filename comes from user input.

📌 Downloading Different Files Dynamically

Route parameters can be used to download different files dynamically.

Dynamic File Download

app.get('/download/:filename', (req, res) => {
  const fileName = req.params.filename;
  const filePath = path.join(__dirname, 'downloads', fileName);

  res.download(filePath);
});

Example requests:
/download/sample.pdf
/download/report.xlsx

âš ī¸ Securing Dynamic Downloads

Never use user-provided filenames directly without validation. Restrict downloads to approved directories and validate file names to prevent unauthorized file access.

Simple Filename Validation

const allowedFiles = ['sample.pdf', 'report.xlsx', 'image.png'];

app.get('/download/:filename', (req, res) => {
  const fileName = req.params.filename;

  if (!allowedFiles.includes(fileName)) {
    return res.status(404).send('File not found.');
  }

  const filePath = path.join(__dirname, 'downloads', fileName);

  res.download(filePath);
});

🔄 File Download Workflow

Browser
Request Download
Browser Downloads File
Express Server
Locate File
Set Download Headers

📚 Download Request Lifecycle

📊 Common File Download Methods

MethodPurpose
res.download()Downloads a file as an attachment.
res.sendFile()Sends a file for display or download depending on the browser.
res.attachment()Sets the response as an attachment before sending data.

🔍 res.download() vs res.sendFile()

Featureres.download()res.sendFile()
Browser BehaviorPrompts file download.May display the file directly.
Content-Disposition HeaderAutomatically set as attachment.Not automatically set.
Best Use CaseReports, PDFs, ZIP files, invoices.HTML pages, images, videos, documents for viewing.

💡 Best Practices

  • Store downloadable files in a dedicated directory.
  • Validate filenames before accessing the filesystem.
  • Use path.join() to create safe file paths.
  • Handle download errors gracefully.
  • Provide meaningful filenames for downloaded files.
  • Restrict access to confidential files using authentication and authorization.

Best Practice

For applications where users download sensitive files, verify user permissions before calling res.download() and avoid exposing internal directory structures.

📚 Learn More

Explore the official Express.js documentation:
â€ĸ Express.js API - res.download()
â€ĸ Express.js API - res.sendFile()
â€ĸ Express.js Official Documentation

📝 Summary

Summary

Express.js simplifies file downloads with the res.download() method, which sends files as downloadable attachments. By combining secure file handling, proper validation, custom filenames, and robust error handling, you can implement reliable and secure file download functionality in your Express.js applications.