fix(frontend): 影片上傳上限 500→90MB 對齊 nginx,解 HTTP 413

stage 推論工作區上傳影片撞 nginx client_max_body_size 100M 回 413,
但前端影片上限標 500MB(af44a9f 只改前端沒同步 nginx)。

過渡修復:MAX_VIDEO_BYTES 調回 90MB,留 10MB buffer 給 multipart
overhead(boundary/header/deviceId 欄位),可靠避開 100M 硬上限。
未來影片改走 localhost 直連(ADR-019)後可放寬此值。

- media.ts:94 MAX_VIDEO_BYTES 500→90MB + 註解說明過渡性質
- media.test.ts 常數斷言 + 邊界 89/90/91MB
- i18n zh-Hant/en 影片 hint 500→90MB
- 模型上傳(500MB)/圖片(20MB)/批次上限未動

Reviewer: Approve(0 Critical/Major/Minor)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
jim800121chen 2026-07-26 21:17:39 +08:00
parent 9397a4d31f
commit c595bb8b91
4 changed files with 9 additions and 9 deletions

View File

@ -362,7 +362,7 @@ export const en: Dictionary = {
"workspace.media.image.primary": "Drag an image here to run inference", "workspace.media.image.primary": "Drag an image here to run inference",
"workspace.media.image.hint": "JPG or PNG · up to 20 MB", "workspace.media.image.hint": "JPG or PNG · up to 20 MB",
"workspace.media.video.primary": "Drag a video here to run inference", "workspace.media.video.primary": "Drag a video here to run inference",
"workspace.media.video.hint": "MP4 / AVI / MOV / MPEG · up to 500 MB", "workspace.media.video.hint": "MP4 / AVI / MOV / MPEG · up to 90 MB",
"workspace.media.video.frame": "Frame", "workspace.media.video.frame": "Frame",
"workspace.media.video.seek": "Seek video", "workspace.media.video.seek": "Seek video",
"workspace.media.batch.primary": "Drag images here (up to 50) for batch inference", "workspace.media.batch.primary": "Drag images here (up to 50) for batch inference",

View File

@ -350,7 +350,7 @@ export const zhHant: Dictionary = {
"workspace.media.image.primary": "將圖片拖曳到此處開始推論", "workspace.media.image.primary": "將圖片拖曳到此處開始推論",
"workspace.media.image.hint": "JPG 或 PNG · 上限 20 MB", "workspace.media.image.hint": "JPG 或 PNG · 上限 20 MB",
"workspace.media.video.primary": "將影片拖曳到此處開始推論", "workspace.media.video.primary": "將影片拖曳到此處開始推論",
"workspace.media.video.hint": "MP4 / AVI / MOV / MPEG · 上限 500 MB", "workspace.media.video.hint": "MP4 / AVI / MOV / MPEG · 上限 90 MB",
"workspace.media.video.frame": "影格", "workspace.media.video.frame": "影格",
"workspace.media.video.seek": "影片跳轉", "workspace.media.video.seek": "影片跳轉",
"workspace.media.batch.primary": "將圖片拖曳到此處(最多 50 張)進行批次推論", "workspace.media.batch.primary": "將圖片拖曳到此處(最多 50 張)進行批次推論",

View File

@ -59,16 +59,16 @@ describe("media validation", () => {
expect(validateVideoFile(makeFile("v.jpg"))?.code).toBe("TYPE"); expect(validateVideoFile(makeFile("v.jpg"))?.code).toBe("TYPE");
}); });
it("影片:上限為 500 MB常數校驗", () => { it("影片:上限為 90 MB常數校驗", () => {
expect(MAX_VIDEO_BYTES).toBe(500 * 1024 * 1024); expect(MAX_VIDEO_BYTES).toBe(90 * 1024 * 1024);
}); });
it("影片:499 MB 通過,剛好 500 MB 通過501 MB 擋 SIZE邊界", () => { it("影片:89 MB 通過,剛好 90 MB 通過91 MB 擋 SIZE邊界", () => {
const mb = 1024 * 1024; const mb = 1024 * 1024;
expect(validateVideoFile(makeSizedFile("v.mp4", 499 * mb))).toBeNull(); expect(validateVideoFile(makeSizedFile("v.mp4", 89 * mb))).toBeNull();
// 剛好等於上限validateVideoFile 用 > 判斷,等於上限應通過 // 剛好等於上限validateVideoFile 用 > 判斷,等於上限應通過
expect(validateVideoFile(makeSizedFile("v.mp4", 500 * mb))).toBeNull(); expect(validateVideoFile(makeSizedFile("v.mp4", 90 * mb))).toBeNull();
expect(validateVideoFile(makeSizedFile("v.mp4", 501 * mb))?.code).toBe("SIZE"); expect(validateVideoFile(makeSizedFile("v.mp4", 91 * mb))?.code).toBe("SIZE");
}); });
it("批次:空陣列 → EMPTY超過 50 → COUNT含非圖 → TYPE", () => { it("批次:空陣列 → EMPTY超過 50 → COUNT含非圖 → TYPE", () => {

View File

@ -91,7 +91,7 @@ export const VIDEO_ACCEPT = ".mp4,.avi,.mov,.mpeg,.mpg";
/** 前端上傳大小上限(防呆;影片經 tunnel 有 timeout 考量,見評估 R-M2。 */ /** 前端上傳大小上限(防呆;影片經 tunnel 有 timeout 考量,見評估 R-M2。 */
export const MAX_IMAGE_BYTES = 20 * 1024 * 1024; // 20 MB export const MAX_IMAGE_BYTES = 20 * 1024 * 1024; // 20 MB
export const MAX_VIDEO_BYTES = 500 * 1024 * 1024; // 500 MB大檔經 tunnelcaller 端 timeout 設 0 = 不限,見 workspace-client VIDEO_UPLOAD_TIMEOUT_MS export const MAX_VIDEO_BYTES = 90 * 1024 * 1024; // 90 MB過渡值對齊 nginx client_max_body_size 100M留 10 MB buffer 給 multipart overhead避免 HTTP 413。未來影片走 localhost 直連後可放寬
export interface UploadMediaOptions { export interface UploadMediaOptions {
/** 上傳進度 callback0~100 */ /** 上傳進度 callback0~100 */