import Busboy from 'busboy';
import type { Request, Response } from 'express';
export function upload(req: Request, res: Response) {
const bb = Busboy({ headers: req.headers, limits: { fileSize: 10 * 1024 * 1024 } });
let bytes = 0;
bb.on('file', (_name, stream, info) => {
if (!['image/png', 'image/jpeg'].includes(info.mimeType)) {
stream.resume();
return;
}
stream.on('data', (chunk) => (bytes += chunk.length));
stream.on('limit', () => res.status(413).end());
stream.on('end', () => {
res.status(200).json({ ok: true, bytes });
});
});
req.pipe(bb);
}
Multipart uploads can blow up memory if you parse them naively. With busboy, I stream file data as it arrives and enforce size limits and content-type checks early. I avoid writing to disk unless I need it; for many flows I stream directly to object storage. The most important detail is setting hard limits so a client can’t send a 5GB file and tie up your server—return 413 when you hit the cap. I also handle ‘field’ parts separately and validate them just like JSON bodies. Once uploads are streaming, peak memory stays stable.