File download with streams in ExpressJS

File download with streams in ExpressJS

To increase the performance of our application in ExpressJS when we need to implement file downloads, we can use the Node.js streams.

To increase the performance of our application in ExpressJS when we need to implement file downloads, we can use the Node.js streams.

The core fs module of Node.js allows us to create a read stream using the createReadStream() method. The stream thus created from a path in the file system can be redirected to the output stream of the response object managed by ExpressJS.

We simply need to add the correct HTTP headers to serve the file and allow it to be downloaded.

'use strict';

const fs = require('fs');
const FILES_PATH = '../files';
const express = require('express');
const File = require('../models/file');
const router = express.Router();


router.get('/download/:id', async (req, res, next) => {
    const { id } = req.params;
    try {
        const file = await File.findById(id);
        if(!file) {
            return res.sendStatus(404);
        }
        
        const filePath = FILES_PATH . '/' . file.path;
        const data = fs.createWriteStream(filePath);
        const disposition = 'attachment; filename="' + file.name + '"';
        
        res.setHeader('Content-Type', file.mime);
        res.setHeader('Content-Disposition', disposition);
        
        data.pipe(res);
    } catch(err) {
        res.sendStatus(500);
    }
});

module.exports = router;

In this example, the information and metadata of the files are saved in the database and found dynamically in the route that allows the download of a specific file.

This is a solution that allows you to have a significant increase in performance especially with large files.