fix(upload): 作品上传上限 100MB -> 150MB(R225)

现象:教师组反馈作品压缩包上传失败。生产日志证实为
nodejs.MultipartFileTooLargeError(今日 10 次:jiaoshi 8 次 / benke 2 次,
10:37~11:07 密集出现)。

根因:作品上传的唯一通道是 POST /api/upload/:group 单次流式整包
(分片通道前端已于 R43 删除,仅服务端保留),因此全组共用同一个
config.multipart.fileSize='100mb';而前端 uploadCombo.ZIP_MAX 长期承诺
200MB ⇒ 100~200MB 的 zip 被前端放行、被后端拒收。日志里的请求耗时
仅 322~665ms,是 nginx(proxy_request_buffering 默认 on)缓冲完整 body
后一次性转发、Node 在内网回环速度下读完并超限报错的时间,与「用户已
耗时数分钟上传完才看到失败」并不矛盾。

改动:
- config.multipart.fileSize: '100mb' -> '150mb',并在注释里标明这是
  所有 multipart 通道的唯一上限,须与 frontend uploadCombo.MAX_MB、
  nginx client_max_body_size 三处同步。
- app/controller/upload.js: docstring 里「最大 50MB」早已失效,
  改为指向配置项,避免再次漂移。

三层限额核对:frontend 150MB = backend 150MB (157286400 B)
< nginx client_max_body_size 200m (209715200 B),nginx 留出余量。

验证:生产 config 去 CR md5 与仓库一致(改动前 c9b997fd…),
仅本改动一项差异;重启后 6s 就绪,/api/health 返 db:"ok"。
This commit is contained in:
2026-10-23 11:19:17 +08:00
parent c15b46a0f9
commit 7bca48369f
2 changed files with 14 additions and 2 deletions

View File

@@ -48,7 +48,10 @@ class UploadController extends Controller {
* 上传作品文件 * 上传作品文件
* POST /api/upload/:group * POST /api/upload/:group
* *
* 支持 .pdf / .doc / .docx / .ppt / .pptx / .zip 格式,最大 50MB * 支持 .pdf / .doc / .docx / .ppt / .pptx / .zip 格式,最大 150MB
* (🔴 R225:原注释写「最大 50MB」早已失效,实际上限只由
* config.multipart.fileSize 决定,当时为 '100mb',现为 '150mb'。
* 本注释不再复述数字,改为指向配置项,避免再次漂移。)
*/ */
async upload() { async upload() {
const { ctx, service } = this; const { ctx, service } = this;

View File

@@ -379,7 +379,16 @@ module.exports = (appInfo) => {
// ----------------------------------------------------------------- // -----------------------------------------------------------------
config.multipart = { config.multipart = {
mode: 'stream', mode: 'stream',
fileSize: '100mb', // 🔴 2026-10-23 R225:'100mb' -> '150mb'
// 缘由:教师组(jiaoshi)作品上传唯一通道 = POST /api/upload/:group 单次流式整包
// (分片通道前端已于 R43 删除),故全组共用这一个硬闸门。原值与前端
// uploadCombo.ZIP_MAX=200MB 长期不一致 ⇒ 100~200MB 的 zip 前端放行、后端拒收
// (MultipartFileTooLargeError),多位教师报障。
// ⚠️ 本值是**所有** multipart 通道的唯一上限,调整时须与下列三处同步:
// frontend/src/utils/uploadCombo.js (ZIP_MAX / OTHER_MAX)
// frontend/src/views/Competition.vue (同上常量 + 文案)
// deploy/competition_website.conf (client_max_body_size 200m,须 > 本值)
fileSize: '150mb',
whitelist: [ whitelist: [
// 文档类 // 文档类
'.pdf', '.pdf',