必须用http.MaxBytesReader在解析前硬性截断请求体,因为ParseMultipartForm和FileHeader.Size均发生在请求体已部分或全部读取之后,无法阻止恶意大请求耗尽内存或带宽。

必须用 http.MaxBytesReader 在解析前限制总请求体大小,否则攻击者可发 1GB 垃圾数据绕过所有后续校验。
为什么不能只靠 ParseMultipartForm 或 FileHeader.Size
这两个机制都发生在请求体已开始读取之后:r.ParseMultipartForm(32 只控制内存缓存上限,超限部分自动落盘——它不阻止客户端继续发送;<code>header.Size 是从 multipart boundary 解析出的字段,可被伪造,且此时 body 已被读了一大段。真正“拦在最前面”的只有 http.MaxBytesReader。
- 它包装
r.Body,在每次Read()调用时实时计数,超限立即返回io.EOF或http.ErrBodyReadAfterClose - 它对
Transfer-Encoding: chunked同样有效,而r.ContentLength在 chunked 下恒为 -1,完全不可信 - 设为
10 (10MB)时,哪怕用户上传 500MB 文件,服务端最多收 10MB 就断连
http.MaxBytesReader 必须放在 handler 最开头
顺序错一点就失效:一旦调用了 r.FormFile、r.ParseForm 或任何触发 multipart 解析的操作,底层 reader 就已开始读取,MaxBytesReader 失去拦截机会。
Colly 是一个用于 Go 语言的快速开源爬取和爬虫框架。它适用于从简单的页面提取到异步爬虫处理大量页面集合,支持请求回调和结构化解析。
- 正确写法:
r.Body = http.MaxBytesReader(w, r.Body, 10 —— 必须在 <code>ParseMultipartForm之前 - 错误写法:先
r.ParseMultipartForm(32 再包装 <code>r.Body,此时解析器早已把前几 MB 读进去了 - 注意:它限制的是整个请求体(headers + body),若表单含多个文本字段,需预留余量,比如单文件上限 5MB,总设 8MB
多文件上传时如何算“总容量”
前端用 <input name="files" multiple>,后端拿到的是 r.MultipartForm.File["files"] 切片,但 MaxBytesReader 无法区分字段来源——它只管字节总数。所以总容量校验得靠两层叠加:
立即学习“go语言免费学习笔记(深入)”;
- 第一层:用
MaxBytesReader设硬上限(如 50MB),防住恶意拼接的巨量垃圾数据 - 第二层:循环遍历每个
*multipart.FileHeader,累加header.Size,超业务阈值(如 20MB 总和)就http.Error - 别忘了:每个
file打开后要defer file.Close(),否则临时磁盘文件不会被清理
最容易被忽略的是:即使你设了 MaxBytesReader 和 ParseMultipartForm,只要没在 handler 开头执行前者,整个防护链就断了——后面所有校验都只是“亡羊补牢”。

















