router.MaxMultipartMemory仅控制multipart解析时内存缓冲上限(默认32 MiB),不设文件大小限制。

router.MaxMultipartMemory 只控制内存缓冲,不等于文件大小限制
router.MaxMultipartMemory 设置的是 multipart 解析时允许加载到内存的最大字节数(单位是字节),默认 32 MiB(即 32 )。它**不是**上传文件总大小的硬性闸门:当文件超过该值,Gin 会自动把超出部分写入系统临时目录(如 <code>/tmp),整个上传仍会成功,只是性能下降、磁盘占用增加。你改了 router.MaxMultipartMemory = 1 却没报错,正是因为这个机制在起作用——它不拒绝大文件,只决定“多少放内存、多少落磁盘”。
真正限制上传总大小,得用 gin-contrib/size 中间件
官方没提供开箱即用的全局文件大小拦截,必须引入第三方中间件:github.com/gin-contrib/size。它基于 Content-Length 请求头做前置校验,在解析 multipart 前就拒绝超限请求,避免无效 IO 和临时文件堆积。
实操步骤:
- 安装:
go get github.com/gin-contrib/size - 在路由初始化后、注册 handler 前插入中间件:
r.Use(size.RequestSizeLimiter(8 (限制 8 MiB) - 注意:该中间件对所有
POST/PUT等含 body 的请求生效,若只想限制上传接口,应放在具体路由组下,而非全局r.Use() - 错误响应是标准
413 Payload Too Large,无需额外处理
如果不用中间件,只能手动在 handler 里校验
不依赖外部包时,唯一可靠方式是在每个上传 handler 开头读取 c.Request.ContentLength,并与阈值比对:
const maxUploadSize = 8 << 20 // 8 MiB
if c.Request.ContentLength > maxUploadSize {
c.AbortWithStatusJSON(http.StatusRequestEntityTooLarge, gin.H{"error": "file too large"})
return
}
但要注意几个坑:
-
Content-Length可能被代理或前端篡改,仅作参考,不能替代中间件级防护 - 多文件上传时,
Content-Length是整个 multipart body 总长(含字段、边界、文件内容),不是单个文件大小 - 某些客户端(尤其带分块上传逻辑的)可能不发
Content-Length,此时该值为 -1,需配合其他策略(如超时、流式读取计数)
别混淆 ParseMultipartForm 和 MaxMultipartMemory
c.Request.ParseMultipartForm() 是手动触发解析的函数,参数是内存阈值(和 MaxMultipartMemory 作用一致),但它只影响当前请求的解析行为;而 router.MaxMultipartMemory 是全局默认值,被 c.FormFile 或 c.MultipartForm 内部调用时使用。二者都不校验总大小,也不抛出错误——它们的设计目标本就是“尽力解析”,而非“安全拦截”。真要拦,必须在外围做。


















