You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 17:06:05