How to stream file downloads in Node.js

Streaming file downloads is essential for Node.js applications serving large files efficiently without consuming excessive memory. As the creator of CoreUI with over 11 years of Node.js development experience since 2014, I’ve optimized file serving in numerous enterprise applications. The most effective solution is to use Node.js streams with createReadStream to pipe files directly to the response. This approach handles files of any size efficiently while maintaining low memory usage.

Use createReadStream and pipe to stream file downloads in Node.js.

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

const app = express()

app.get('/download/:filename', (req, res) => {
  const filename = req.params.filename
  const filepath = path.join(__dirname, 'files', filename)

  // Check if file exists
  if (!fs.existsSync(filepath)) {
    return res.status(404).json({ error: 'File not found' })
  }

  // Get file stats
  const stat = fs.statSync(filepath)

  // Set headers
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`)
  res.setHeader('Content-Type', 'application/octet-stream')
  res.setHeader('Content-Length', stat.size)

  // Create read stream and pipe to response
  const readStream = fs.createReadStream(filepath)

  readStream.on('error', (error) => {
    console.error('Stream error:', error)
    if (!res.headersSent) {
      res.status(500).json({ error: 'Error streaming file' })
    }
  })

  readStream.pipe(res)
})

The createReadStream() creates a readable stream from the file without loading it into memory. The pipe() method automatically handles backpressure and data flow to the response. Setting Content-Disposition triggers browser download behavior with the specified filename. Error handling ensures graceful failure if the stream encounters issues. This approach scales to files of any size without memory concerns.

Best Practice Note

This is the same streaming approach we use in CoreUI backend systems for efficient file serving. For enhanced security, validate and sanitize filenames to prevent path traversal attacks. Consider implementing range request support for resumable downloads and media streaming by checking the Range header and using createReadStream with start and end options.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author

Subscribe to our newsletter
Get early information about new products, product updates and blog posts.
How to Open Link in a New Tab in HTML?
How to Open Link in a New Tab in HTML?

How to loop through an array in JavaScript
How to loop through an array in JavaScript

How to Use Bootstrap Dropdown in Angular – CoreUI Integration Guide
How to Use Bootstrap Dropdown in Angular – CoreUI Integration Guide

How to Remove Elements from a JavaScript Array
How to Remove Elements from a JavaScript Array

Answers by CoreUI Core Team