ExpressJS中如何关闭Busboy连接并返回文件大小超限错误响应
实现方案
核心思路
- 实时校验大小:不要等文件全部上传完成才校验,在
data事件累加文件大小的阶段就做判断,超过阈值直接终止上传,节省服务端带宽 - 标记超限状态:增加全局状态标记避免重复返回响应,防止报「响应头已设置」的错误
- 符合HTTP语义:超限返回413(Payload Too Large)状态码,方便前端统一识别
修改后完整代码
const express = require('express'); const Busboy = require('busboy'); const app = express(); // 按需调整最大允许上传大小,示例为10MB const MAXIMUM_ALLOWED_FILE_UPLOAD_SIZE = 10 * 1024 * 1024; app.post('/upload', (req, res) => { const busboy = Busboy({ headers: req.headers }); // 全局标记:是否已经触发大小超限,避免重复返回响应 let isLimitExceeded = false; busboy.on('file', function(fieldname, file, filename, encoding, mimetype) { console.log('File [' + fieldname + ']: filename: ' + filename + ', encoding: ' + encoding + ', mimetype: ' + mimetype); let fileSize = 0; file.on('data', function(data) { // 已触发超限直接跳过后续处理 if (isLimitExceeded) return; fileSize += data.length; // 实时校验大小 if (fileSize > MAXIMUM_ALLOWED_FILE_UPLOAD_SIZE) { isLimitExceeded = true; // 消耗剩余流数据避免请求卡住,也可以用file.destroy(),但需要额外处理销毁异常 file.resume(); // 返回超限响应 return res.status(413).json({ code: 413, msg: `文件大小超出限制,最大允许${MAXIMUM_ALLOWED_FILE_UPLOAD_SIZE / 1024 / 1024}MB` }); } // 正常的文件流处理逻辑,比如写入本地文件、上传到对象存储等 console.log('File [' + fieldname + '] got ' + data.length + ' bytes'); }); file.on('end', function() { if (isLimitExceeded) return; console.log('File [' + fieldname + '] 上传完成'); fileSize = 0; }); }); busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) { if (isLimitExceeded) return; console.log('Field [' + fieldname + ']: value: ' + val); }); // 所有内容解析完成后,未超限的情况返回成功响应 busboy.on('finish', () => { if (!isLimitExceeded) { res.json({ code: 200, msg: '上传成功' }); } }); // 异常处理 busboy.on('error', (err) => { console.error('解析错误', err); if (!isLimitExceeded) { isLimitExceeded = true; res.status(500).json({ code: 500, msg: '上传失败' }); } }); req.pipe(busboy); });
注意事项
如果有同时上传多个文件的需求,只要其中一个文件触发超限,全局标记就会生效,后续所有文件/字段的处理都会跳过,避免服务端做无用功。如果需要允许其他文件继续上传,只拦截超限的单个文件,可以把标记逻辑放到
file事件内部,不用全局标记即可。
内容的提问来源于stack exchange,提问作者ololo
相关产品推荐
相关产品推荐

