maxmultipartmemory仅控制multipart解析时内存缓冲上限,超限自动落盘不报错,无法拦截大文件;真正限制需在c.formfile后校验file.size。

router.MaxMultipartMemory 只控制解析 multipart 表单时内存缓冲区上限,不是文件总大小限制。设成 1(即 8 MiB)后上传 100 MiB 文件仍能成功,是因为 Gin 会自动把超出部分写入临时磁盘文件,不报错——这正是你遇到的“不起作用”的根本原因。
MaxMultipartMemory 的真实作用和边界
它只影响
c.FormFile和c.MultipartForm解析阶段:决定多少字节先缓存在内存里,超了就 fallback 到临时文件不触发任何错误、不中断请求、不校验最终文件大小
默认值是
32 (32 MiB),设为 <code>8 只是让更早落盘,对“拒绝大文件”毫无帮助如果你靠它做上传拦截,永远收不到预期的
http.StatusBadRequest它和 HTTP 层的
Content-Length无关,也不会读取完再判断在高并发场景下,调小它可降低内存压力,但必须配合后续校验才安全
真正限制文件大小的两种可靠方式
用 c.FormFile 获取文件后,立刻检查 file.Size:
file, err := c.FormFile("file")
if err != nil {
c.String(http.StatusBadRequest, "no file received")
return
}
if file.Size > 10<p>用 <code>c.Request.FormFile</code>(标准库方式)获取 <code>multipart.FileHeader</code> 后同样读 <code>Size</code> 字段:</p>
-
c.FormFile和c.Request.FormFile返回的*multipart.FileHeader都带Size字段,这是客户端在上传前已知并填入的,可信 - 不要等
SaveUploadedFile完成后再检查,那已经晚了 - 多文件场景下,遍历
form.File["files"]逐个检查file.Size
为什么不能只依赖中间件或全局配置
Gin 没有内置“上传大小拦截中间件”,也没有类似 Express 的 multer.limit() 那种声明式限制:
MaxMultipartMemory是底层解析参数,不是业务规则第三方中间件(如
gin-contrib/size)往往也是基于Content-Length做 header 拦截,但不可靠:有些客户端不发该 header,或用分块传输(chunked encoding)绕过最稳妥的点永远在 handler 内:拿到
FileHeader后第一件事就是if file.Size > X-
若需统一处理,可封装一个工具函数:
func checkFileSize(file *multipart.FileHeader, max int64) error { if file.Size > max { return fmt.Errorf("file size %d exceeds limit %d", file.Size, max) } return nil }然后在每个上传 handler 里调用
真正起效的限制一定发生在你显式读取 file.Size 并比较之后。别被 MaxMultipartMemory 的命名误导——它管内存,不管准入。











