forked from EduCraft/curriculum-project-hub
fix(filelib): 上传上限抬到 50MiB,并把它与 body limit 的串联写清
7.8MB 文件上传报 413:那是 Fastify 在 body 解析阶段拒的,不是 HUB_FILELIB_MAX_FILE_BYTES。上传把内容放在 JSON body 里、二进制过 base64 体积涨 4/3,所以有效上限是 min(该值, HUB_HTTP_BODY_LIMIT_BYTES × 3/4)。 原先 body limit 是 1MiB,10MiB 的文件上限根本不可达。 .env.example:body limit 1MiB → 70MiB,新增 HUB_FILELIB_MAX_FILE_BYTES=50MiB。 注意 body limit 同时是 ADR-0022 requestBodySize 维度的平台 ceiling,抬高它 对所有端点生效。 resolveMaxFileBytes 拆成 parseMaxFileBytes(纯解析)+ resolveMaxFileBytes(读 env):原先带默认参数,显式传 undefined 会回落到读 env,"没传值"与"读环境变量" 分不开,vitest 加载 .env 后测试会读到真实配置。
This commit is contained in:
@@ -22,16 +22,32 @@ export const FILE_PATH_MAX_DEPTH = 32;
|
||||
export const FILE_CONTENT_MAX_BYTES_DEFAULT = 10 * 1024 * 1024;
|
||||
|
||||
/**
|
||||
* 单文件字节上限:`HUB_FILELIB_MAX_FILE_BYTES` 覆盖,缺省 10MiB。
|
||||
* 非法值(非正整数/NaN)按缺省处理 —— 配置写错不该让上传静默变成 0 上限。
|
||||
* 单文件字节上限的纯解析。非法值(非正整数/NaN)按缺省处理 ——
|
||||
* 配置写错不该让上传静默变成 0 上限(那会把每次上传都拒掉)。
|
||||
*
|
||||
* 与 `resolveMaxFileBytes` 分开是有意的:带默认参数的单函数版本里,
|
||||
* 显式传 undefined 会触发默认值、回到读 env,于是“没传值”和“读环境变量”
|
||||
* 永远分不开,测试也会被 vitest 加载的 .env 干扰。
|
||||
*/
|
||||
export function resolveMaxFileBytes(raw: string | undefined = process.env["HUB_FILELIB_MAX_FILE_BYTES"]): number {
|
||||
export function parseMaxFileBytes(raw: string | undefined): number {
|
||||
if (raw === undefined || raw.trim() === "") return FILE_CONTENT_MAX_BYTES_DEFAULT;
|
||||
const parsed = Number(raw.trim());
|
||||
if (!Number.isSafeInteger(parsed) || parsed <= 0) return FILE_CONTENT_MAX_BYTES_DEFAULT;
|
||||
return parsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生效上限:`HUB_FILELIB_MAX_FILE_BYTES` 覆盖,缺省 10MiB。
|
||||
*
|
||||
* 注意它与 `HUB_HTTP_BODY_LIMIT_BYTES` 是串联的:上传把内容放在 JSON body 里,
|
||||
* 二进制过 base64 体积涨 4/3,所以真正的天花板是
|
||||
* min(本值, bodyLimit × 3/4)。body limit 太小时本值不可达,而且报错发生在
|
||||
* Fastify 解析阶段(413 Payload Too Large),根本到不了下面的 checkSize。
|
||||
*/
|
||||
export function resolveMaxFileBytes(): number {
|
||||
return parseMaxFileBytes(process.env["HUB_FILELIB_MAX_FILE_BYTES"]);
|
||||
}
|
||||
|
||||
const CONTROL_CHARS = /[\p{C}]/u;
|
||||
const FORBIDDEN_SEGMENTS = new Set(["", ".", "..", ".git"]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user