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.