Busboy Streaming Multipart Limits

Parse multipart request bodies with Busboy in streaming mode, enforcing file count, size, and type limits before any bytes hit disk.

TypescriptNodeFile Upload

Code

snippet
import busboy from 'busboy';
import { createWriteStream } from 'node:fs';
import { pipeline } from 'node:stream/promises';
import type { IncomingMessage } from 'node:http';

const LIMITS = {
  fileSize: 10 * 1024 * 1024,
  files: 2,
  fields: 12,
};

const ALLOWED_TYPES = /^(image\/png|image\/webp|application\/pdf)$/;

export function handleUpload(req: IncomingMessage): Promise<{
  files: { name: string; bytes: number }[];
  fields: Record<string, string>;
}> {
  return new Promise((resolve, reject) => {
    const parser = busboy({
      headers: req.headers,
      limits: LIMITS,
    });

    const files: { name: string; bytes: number }[] = [];
    const fields: Record<string, string> = {};

    parser.on('file', (name, stream, info) => {
      if (!ALLOWED_TYPES.test(info.mimeType)) {
        stream.resume(); // 必须消费掉流,否则解析停滞
        reject(new Error('unsupported type: ' + info.mimeType));
        return;
      }
      const target = createWriteStream('uploads/' + info.filename);
      pipeline(stream, target).catch(reject);
      files.push({ name: info.filename, bytes: stream.readableLength });
    });

    parser.on('field', (name, value) => {
      fields[name] = value.slice(0, 500);
    });

    parser.on('close', () => resolve({ files, fields }));
    parser.on('error', reject);

    req.pipe(parser);
  });
}