Stream File Download
Express handler that streams a file to the client with proper headers, range support, and error handling.
import { Request, Response } from 'express';
import fs from 'fs';
import path from 'path';
export function streamDownload(uploadsDir: string) {
return (req: Request, res: Response) => {
const filename = path.basename(req.params.filename);
const filePath = path.join(uploadsDir, filename);
fs.stat(filePath, (err, stats) => {
if (err || !stats.isFile()) {
return res.status(404).json({ error: 'File not found' });
}
const size = stats.size;
const range = req.headers.range;
if (range) {
const [startStr, endStr] = range.replace(/bytes=/, '').split('-');
const start = parseInt(startStr, 10);
const end = endStr ? parseInt(endStr, 10) : size - 1;
res.writeHead(206, {
'Content-Range': `bytes ${start}-${end}/${size}`,
'Accept-Ranges': 'bytes',
'Content-Length': end - start + 1,
'Content-Type': 'application/octet-stream',
});
fs.createReadStream(filePath, { start, end }).pipe(res);
} else {
res.writeHead(200, {
'Content-Length': size,
'Content-Disposition': `attachment; filename=\"${filename}\"`,
'Content-Type': 'application/octet-stream',
});
fs.createReadStream(filePath).pipe(res);
}
});
};
}
// Usage:
// app.get('/download/:filename', streamDownload('./uploads'));Use Cases
- Large file downloads
- Resumable downloads
- Media streaming
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
File Upload with Multer
Configure Multer for disk storage with file type validation, size limits, and unique filenames for Express.
JWT Verify Middleware
Express middleware that verifies JWT tokens from the Authorization header and attaches the decoded payload to the request.
In-Memory Rate Limiter for Express
Token bucket rate limiter middleware for Express with configurable window and max requests per IP.
Async Error Handler Wrapper
Higher-order function that wraps async Express route handlers and forwards rejected promises to error middleware.