fiber 的 bodylimit 中间件不能直接限制文件上传大小,因为它仅按 content-length 限制整个请求体字节数,不解析 multipart 结构,无法区分纯 json 与 form-data;实际文件上传因 boundary 和字段开销导致体积膨胀,易误判。

为什么 Fiber 的 BodyLimit 中间件不能直接限制文件上传大小
Fiber 的 BodyLimit 中间件只限制整个 HTTP 请求体(Content-Length)的字节数,而 multipart 文件上传的请求体包含 boundary、表单字段、二进制数据等混合内容。当上传一个 10MB 的文件时,实际请求体可能达到 10.2–10.5MB(取决于字段数和 filename 长度)。单纯靠 BodyLimit("10MB") 容易误杀或漏判——它不识别 multipart 结构,也无法区分「是纯 JSON 还是带文件的 form-data」。
用 multipart.MaxMemory 控制内存中解析上限
Fiber 默认使用 fasthttp 的 multipart 解析器,其核心控制参数是 MaxMemory,它决定多少字节以内的文件会保留在内存(in-memory),超过则写入临时磁盘(由 TempDir 指定)。这个值直接影响你能否在 handler 中安全调用 file.Size() 或 file.Open()。
-
MaxMemory = 0:所有文件都写入磁盘,handler 中需手动清理临时文件 MaxMemory = 32 (即 32MB):≤32MB 的文件进内存,>32MB 的走磁盘- 该设置**不等于**「单文件最大允许大小」,只是解析策略开关;真正校验仍需业务层判断
在 handler 里用 c.MultipartForm() + 显式校验
Fiber 不像 Spring Boot 那样自动抛出 MaxUploadSizeExceededException,必须手动检查 *multipart.Form 中每个 *multipart.FileHeader 的 Size 字段。常见错误是只校验第一个文件、忽略多文件场景、或没处理空文件。
app.Post("/upload", func(c *fiber.Ctx) error {
form, err := c.MultipartForm()
if err != nil {
return c.Status(fiber.StatusBadRequest).SendString("parse failed: " + err.Error())
}
for _, files := range form.File {
for _, file := range files {
if file.Size > 50
- 注意
form.File是map[string][]*multipart.FileHeader,键为表单name属性 -
file.Size是真实上传的字节数,已排除 boundary 和元数据开销,可直接比对 - 不要依赖
c.Locals("filename")等中间件注入值做校验——它们可能未设置或被绕过
结合 fasthttp.RequestCtx.SetBodyStreamWriter 做流式预检(高级场景)
当需要拦截超大上传(如 >500MB)并避免内存/磁盘浪费时,MultipartForm() 已不适用——它会先完整解析再返回。此时需绕过 Fiber 默认解析,用底层 fasthttp 的流式读取,在读取过程中累计字节数,一旦超限立即中断连接。
- 这要求你禁用 Fiber 的自动 body 解析:
app.Use(func(c *fiber.Ctx) error { return c.Next() })不调用c.Body()或c.MultipartForm() - 直接操作
c.Context().Request.BodyWriter()或注册自定义BodyStream - 实际项目中极少需要此方案;多数情况用前三个方法已足够
真正容易被忽略的是:Fiber 没有「全局上传大小兜底」机制,BodyLimit 和 MaxMemory 各管一段,最终校验必须落在 handler 内——漏掉任意一环,恶意用户就能绕过限制。











