From 1a6707cac3cb6caf8e9b168b3559f33f653190b3 Mon Sep 17 00:00:00 2001 From: qubiaobiao <3294694717@qq.com> Date: Fri, 23 Oct 2026 11:19:18 +0800 Subject: [PATCH] =?UTF-8?q?fix(upload):=20=E4=B8=8A=E4=BC=A0=E4=B8=8A?= =?UTF-8?q?=E9=99=90=E7=BB=9F=E4=B8=80=20150MB=20+=20=E8=B6=85=E6=97=B6?= =?UTF-8?q?=E6=94=BE=E5=AE=BD=E8=87=B3=20600s=EF=BC=88R225=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 背景:教师组作品压缩包上传失败,根因是后端 config.multipart.fileSize 为 '100mb',而前端一直承诺 zip 200MB / 其他 100MB —— 两套阈值互不知情, 100~200MB 的文件必然「前端放行、后端拒收」。 改动: - utils/uploadCombo.js: 新增 MAX_MB=150 作为唯一数值源,ZIP_MAX / OTHER_MAX 均取 MAX_MB;validateSingleFile 的提示文案改为「150MB」。 原先 zip 200MB 是**无法兑现的承诺**(后端从来只收 100MB),收紧到 150 是让提示与事实一致,不是新增限制。 - views/Competition.vue: 删除本文件内另一份 ZIP_MAX=200MB/OTHER_MAX=100MB 的副本(本来就没被引用,但重复常量正是漂移温床),改为从 uploadCombo 导入 MAX_MB,三处文案同步为「单个文件 150MB」。 - api/upload.js: uploadWork 的 timeout 300s -> 600s。150MB 在服务器入口 约 1.25MB/s 且为全体考生共享,单传约 120s、数人并发可达 400s+;不放宽 超时的话,限额放开后失败方式只会从「文件太大」变成「超时」。 nginx /api/ 的 proxy_send_timeout / proxy_read_timeout 已是 600s,对齐。 产物验证:新包 Competition-C3sA4cVv.js 含「超过大小限制(150MB)」, 旧文案「zip 200MB / 其他 100MB」0 命中;timeout 压缩形态 timeout:6e5 (=600000)已确认落在 Competition chunk,Admin chunk 的超时未被波及。 --- src/api/upload.js | 6 +++++- src/utils/uploadCombo.js | 12 +++++++++--- src/views/Competition.vue | 14 ++++++++------ 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/api/upload.js b/src/api/upload.js index 18c3eb6..d27ec7f 100644 --- a/src/api/upload.js +++ b/src/api/upload.js @@ -39,8 +39,12 @@ export function uploadWork(group, formData, onProgress) { // 注意:不要手动设置 Content-Type: multipart/form-data(不带 boundary 会导致 // 后端 ctx.getFileStream() 报 Missing boundary 而 500)。交由 axios/浏览器自动 // 补带 boundary 的 multipart 头。字段顺序:先文本字段(file_type/work_name)再 file。 + // 🔴 R225:timeout 300s -> 600s。上传上限提至 150MB 后,服务器入口带宽约 + // 1.25MB/s 且为全体考生共享,单传约 120s、数人并发时可达 400s+; + // 原 300s 会让「限额已放开」的文件改以超时失败。 + // nginx 侧 /api/ 的 proxy_send_timeout/proxy_read_timeout 已是 600s,两者对齐。 return request.post(`/upload/${group}`, formData, { - timeout: 300000, + timeout: 600000, onUploadProgress: (e) => { if (onProgress && e.total) onProgress(Math.round((e.loaded / e.total) * 100)) }, diff --git a/src/utils/uploadCombo.js b/src/utils/uploadCombo.js index 5b54e03..e339dba 100644 --- a/src/utils/uploadCombo.js +++ b/src/utils/uploadCombo.js @@ -13,8 +13,14 @@ */ export const ALLOWED = ['.doc', '.docx', '.pdf', '.ppt', '.pptx', '.zip'] -export const ZIP_MAX = 200 * 1024 * 1024 -export const OTHER_MAX = 100 * 1024 * 1024 +// 上传大小上限:统一 150MB +// 🔴 2026-10-23 R225:原 ZIP_MAX=200MB / OTHER_MAX=100MB,与后端 +// config.multipart.fileSize(当时 '100mb')长期不一致 ⇒ 100~200MB 的 zip +// 前端放行、后端抛 MultipartFileTooLargeError,教师组因此报障。 +// 现前后端统一为 150MB(后端已同步改为 '150mb'),保持「前端放行 == 后端接收」。 +export const MAX_MB = 150 +export const ZIP_MAX = MAX_MB * 1024 * 1024 +export const OTHER_MAX = MAX_MB * 1024 * 1024 export function fileExt(name) { return (String(name).split('.').pop() || '').toLowerCase() @@ -42,7 +48,7 @@ export function validateSingleFile(name, size) { const e = '.' + fileExt(name) if (!ALLOWED.includes(e)) return `不支持的格式:${name}` const max = e === '.zip' ? ZIP_MAX : OTHER_MAX - if (size > max) return `${name} 超过大小限制(${e === '.zip' ? '200MB' : '100MB'})` + if (size > max) return `${name} 超过大小限制(${MAX_MB}MB)` return null } diff --git a/src/views/Competition.vue b/src/views/Competition.vue index b1c0564..84509ea 100644 --- a/src/views/Competition.vue +++ b/src/views/Competition.vue @@ -31,7 +31,7 @@ - 支持 docx / pdf / ppt / zip。规则:① zip 须单独上传(与任何其他文件互斥,自动覆盖);② pdf 与 docx 相互覆盖,只能保留其一;③ 若需同时提交文档与演示稿,请选「pdf + ppt」或「docx + ppt」组合。zip 上限 200MB,其余格式上限 100MB。 + 支持 docx / pdf / ppt / zip。规则:① zip 须单独上传(与任何其他文件互斥,自动覆盖);② pdf 与 docx 相互覆盖,只能保留其一;③ 若需同时提交文档与演示稿,请选「pdf + ppt」或「docx + ppt」组合。单个文件上限 150MB。