在Golang的Web开发中,处理表单文件上传时,合理限制文件大小是保障服务稳定性的重要环节。如果不做限制,恶意用户上传超大文件可能快速耗尽服务器磁盘和内存资源,甚至导致服务崩溃。下面介绍几种常用的文件大小限制实现方式。

通过请求体大小限制上传文件
Golang的net/http包中,http.Request的ParseMultipartForm方法可以解析 multipart 格式的表单数据,该方法接收一个参数表示最大内存使用量,超过该大小的文件部分会存储到临时文件中。我们可以在调用该方法前,先通过MaxBytesReader限制整个请求体的大小,从而间接限制上传文件的大小。
示例代码如下:
package main
import (
"fmt"
"net/http"
)
func uploadHandler(w http.ResponseWriter, r *http.Request) {
// 限制整个请求体最大为10MB,超过则返回错误
r.Body = http.MaxBytesReader(w, r.Body, 10<<20) // 10MB = 10 * 1024 * 1024 字节
// 解析multipart表单,最大内存使用32MB,超过的内存部分存临时文件
err := r.ParseMultipartForm(32 << 20)
if err != nil {
// 如果是请求体过大的错误,返回对应提示
if err == http.ErrMissingBoundary || err.Error() == "http: request body too large" {
http.Error(w, "上传文件大小不能超过10MB", http.StatusRequestEntityTooLarge)
return
}
http.Error(w, "表单解析失败", http.StatusBadRequest)
return
}
// 获取上传的文件
file, _, err := r.FormFile("uploadFile")
if err != nil {
http.Error(w, "获取上传文件失败", http.StatusBadRequest)
return
}
defer file.Close()
// 后续文件处理逻辑
fmt.Fprintf(w, "文件上传成功")
}
func main() {
http.HandleFunc("/upload", uploadHandler)
http.ListenAndServe(":8080", nil)
}
手动校验已上传文件的大小
如果已经获取到了上传的文件句柄,也可以通过Stat方法获取文件的大小,再和预设的上限做对比,这种方式适合已经拿到文件对象后的二次校验。
示例代码如下:
package main
import (
"fmt"
"net/http"
)
func uploadHandlerV2(w http.ResponseWriter, r *http.Request) {
// 限制请求体大小
r.Body = http.MaxBytesReader(w, r.Body, 10<<20)
err := r.ParseMultipartForm(32 << 20)
if err != nil {
http.Error(w, "表单解析失败", http.StatusBadRequest)
return
}
file, header, err := r.FormFile("uploadFile")
if err != nil {
http.Error(w, "获取上传文件失败", http.StatusBadRequest)
return
}
defer file.Close()
// 获取文件大小
fileSize := header.Size
maxSize := int64(10 << 20) // 10MB上限
if fileSize > maxSize {
http.Error(w, "上传文件大小不能超过10MB", http.StatusRequestEntityTooLarge)
return
}
// 后续处理逻辑
fmt.Fprintf(w, "文件大小校验通过,上传成功")
}
func main() {
http.HandleFunc("/upload", uploadHandlerV2)
http.ListenAndServe(":8080", nil)
}
使用中间件统一处理大小限制
如果项目中多个接口都需要上传文件,逐个接口设置限制会比较冗余,可以编写一个中间件统一处理请求体大小限制,所有需要上传文件的路由都经过该中间件即可。
示例代码如下:
package main
import (
"net/http"
)
// 限制请求体大小的中间件,参数maxBytes为最大字节数
func maxSizeMiddleware(maxBytes int64) func(http.HandlerFunc) http.HandlerFunc {
return func(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
r.Body = http.MaxBytesReader(w, r.Body, maxBytes)
next(w, r)
}
}
}
func uploadHandler(w http.ResponseWriter, r *http.Request) {
err := r.ParseMultipartForm(32 << 20)
if err != nil {
if err.Error() == "http: request body too large" {
http.Error(w, "上传文件大小不能超过限制", http.StatusRequestEntityTooLarge)
return
}
http.Error(w, "表单解析失败", http.StatusBadRequest)
return
}
// 后续处理逻辑
w.Write([]byte("上传成功"))
}
func main() {
// 限制上传文件最大10MB,绑定到上传接口
http.HandleFunc("/upload", maxSizeMiddleware(10<<20)(uploadHandler))
http.ListenAndServe(":8080", nil)
}
注意事项
- 设置限制时,
MaxBytesReader的限制是包含整个请求体的大小,包括表单其他字段和文件内容,所以实际设置的上限可以比文件大小上限略大,预留其他表单字段的空间。 - 超出限制后返回的状态码建议使用
413 Request Entity Too Large,符合HTTP规范,前端也可以根据该状态码做对应的提示处理。 - 如果使用的是第三方Web框架,比如Gin,框架本身通常提供了更简便的文件大小限制配置,比如Gin可以通过
router.MaxMultipartMemory设置,但底层逻辑和net/http的实现是一致的。
GolangWeb表单文件大小限制http_handle修改时间:2026-06-24 14:06:19