Fiber 框架需手动实现上传限制:必须用 fiber.BodyLimit 前置拦截总请求体大小,再显式设置 ParseMultipartForm 的 maxMemory 控制内存使用,并校验 file.Size 实现单文件细粒度限制。

Fiber 框架本身不内置文件上传解析和大小限制逻辑,必须靠中间件或手动校验。它默认把原始请求体(包括 multipart)当作字节流交给 handler,不会自动解析 MultipartFile 或抛出类似 Spring 的 MaxUploadSizeExceededException。所以“限制上传大小”这件事,得你主动做。
为什么直接用 c.MultipartForm() 会卡住或 OOM
调用 c.MultipartForm() 时,Fiber 底层会委托 Go 标准库的 http.Request.ParseMultipartForm()。而这个方法在解析前不检查总请求体大小,会先把整个请求读进内存(或临时磁盘),直到解析完成才报错。如果用户发一个 2GB 的恶意文件,你的服务可能先卡死、OOM,再 panic。
- 标准库默认
maxMemory是 32MB(http.MaxBytesReader不介入 multipart 场景) - Fiber 默认不限制
BodyLimit,意味着整个请求体可无限大(除非你配了反向代理或网关拦截) -
c.MultipartForm()报错如http: request body too large是事后行为,已造成资源消耗
用 fiber.BodyLimit 在路由层硬拦截
这是最简单、最前置的防御方式:在进入业务逻辑前,就拒绝超大的请求体。它基于 http.MaxBytesReader,在读取请求体时实时计数,一超限立刻 413。
- 只对当前路由生效,适合统一限制所有上传入口
- 单位必须是字节,不能写
"10MB"—— 要写10 * 1024 * 1024 - 它限制的是整个 HTTP 请求体(含 boundary、表单字段、所有文件),不是单个文件
- 注意:若你用了
fiber.Compress()中间件,需放在BodyLimit之后,否则解压后可能超限
app.Post("/upload", fiber.BodyLimit(20*1024*1024), func(c *fiber.Ctx) error {
// 此处 c.Request().Body 已被限制 ≤20MB
form, err := c.MultipartForm()
if err != nil {
return c.Status(fiber.StatusBadRequest).SendString("解析失败:" + err.Error())
}
return c.SendString("OK")
})
手动校验单个文件大小(用 form.File + file.Size)
如果你需要区分「单文件上限」和「总请求上限」,或者想返回更细粒度的错误(比如“图片不能超过5MB,视频不能超过100MB”),就得在拿到 *multipart.FileHeader 后主动判断 .Size。
-
file.Size是文件实际字节数,可靠,无需打开文件 - 必须在
c.MultipartForm()成功后才能获取,但此时请求体已加载——所以务必配合BodyLimit先兜底 - 不要依赖
Content-Length头,它可能被伪造或不准确(尤其 chunked 编码) - 示例中用
map[string]int64区分字段名做差异化限制
limits := map[string]int64{
"avatar": 5 * 1024 * 1024,
"video": 100 * 1024 * 1024,
}
form, _ := c.MultipartForm()
for field, files := range form.File {
if max, ok := limits[field]; ok {
for _, file := range files {
if file.Size > max {
return c.Status(fiber.StatusBadRequest).
SendString(field + " 文件不能超过 " + humanize.Bytes(uint64(max)))
}
}
}
}
真正安全的组合:BodyLimit + 显式 ParseMultipartForm 控制内存
Go 标准库 ParseMultipartForm 接受一个 maxMemory 参数,决定多少字节以内留在内存,超出则写临时磁盘。Fiber 的 c.MultipartForm() 内部默认用 32MB,但你不控制它,就等于放弃内存使用主导权。
- 显式调用
c.Request().MultipartForm并传入自定义maxMemory,能防止小文件也吃光堆内存 - 比如设
maxMemory = 4 * 1024 * 1024,那么 ≤4MB 的文件走内存,>4MB 的自动落盘 - 这和 Spring 的
file-size-threshold作用一致,但 Fiber 不自动帮你设,必须手写 - 注意:
maxMemory必须 ≤BodyLimit值,否则逻辑矛盾
真正容易被忽略的是:Fiber 没有“配置即生效”的上传模块。每个上传接口都得自己决定用几层防护——BodyLimit 是底线,maxMemory 是内存策略,file.Size 校验是业务规则。少一层,就可能被绕过或拖垮。


















