必须显式调用 ParseMultipartForm 才能解析 multipart 表单,否则 request.MultipartForm 和 request.FormFile 返回 nil 或报错;默认内存上限 32MB,超限报“request body too large”,建议提前设置如 r.ParseMultipartForm(10

使用 request.ParseMultipartForm 解析上传数据
Go 的 http.Request 默认不会自动解析 multipart 表单,必须显式调用 ParseMultipartForm 才能访问 request.MultipartForm 或 request.FormFile。不调用会直接返回 nil 或报错 http: no such file。
注意:该方法内部会读取并缓存整个请求体,若上传文件过大(默认上限 32MB),会触发 http: request body too large。建议提前设置上限:
err := r.ParseMultipartForm(10 << 20) // 10MB
if err != nil {
http.Error(w, "invalid form", http.StatusBadRequest)
return
}
-
ParseMultipartForm参数是最大内存缓存字节数;超出部分会暂存到磁盘临时文件 - 若设为 0,等价于
ParseForm,无法处理文件字段 - 调用后才能安全使用
r.FormFile或遍历r.MultipartForm.File
用 request.FormFile 获取单个文件
适用于表单中只有一个文件字段(如 )的常见场景。它比手动从 MultipartForm.File 取值更简洁,且自动处理了边界情况。
典型错误是忽略返回的 header(*multipart.FileHeader),而直接试图读取 file —— 实际上 file 是一个 io.ReadCloser,需后续读取内容:
立即学习“go语言免费学习笔记(深入)”;
第一步】:将安装包中所有的文件夹和文件用ftp工具以二进制方式上传至服务器空间;(如果您不知如何设置ftp工具的二进制方式,可以查看:(http://www.shopex.cn/support/qa/setup.help.717.html)【第二步】:在浏览器中输入 http://您的商店域名/install 进行安装界面进行安装即可。【第二步】:登录后台,工具箱里恢复数据管理后台是url/sho
file, header, err := r.FormFile("avatar")
if err != nil {
http.Error(w, "no file uploaded", http.StatusBadRequest)
return
}
defer file.Close()
// 保存到磁盘示例
dst, err := os.Create("/tmp/" + header.Filename)
if err != nil {
http.Error(w, "save failed", http.StatusInternalServerError)
return
}
defer dst.Close()
io.Copy(dst, file)
-
header.Size是文件大小(字节),可用于限制上传体积 -
header.Header.Get("Content-Type")可获取客户端声明的 MIME 类型,但不可信,需额外校验 - 务必
defer file.Close(),否则可能泄漏文件描述符
处理多个同名文件或动态字段名
当表单含多个 name="files" 文件输入,或字段名由前端动态生成(如 files[0], files[1]),就不能只依赖 FormFile。此时应直接访问 r.MultipartForm.File map:
if err := r.ParseMultipartForm(32 << 20); err != nil {
http.Error(w, "parse error", http.StatusBadRequest)
return
}
for name, files := range r.MultipartForm.File {
if strings.HasPrefix(name, "files[") {
for _, f := range files {
src, err := f.Open()
if err != nil {
continue
}
defer src.Close() // 注意:这里不能 defer,需在循环内及时关闭
dst, _ := os.Create("/tmp/" + f.Filename)
io.Copy(dst, src)
dst.Close()
}
}
}
-
r.MultipartForm.File是map[string][]*multipart.FileHeader,每个 key 对应表单字段名 - 循环内
defer src.Close()会延迟到函数结束才执行,导致所有文件句柄堆积 —— 必须显式src.Close() - 如果字段名不确定,可先用
r.MultipartForm.Value检查普通文本字段辅助判断
避免临时文件残留和磁盘爆满
Go 在 ParseMultipartForm 中自动创建临时文件时,使用的是 os.TempDir()(通常是 /tmp)。若上传频繁或大文件未及时清理,可能占满磁盘。
有两条关键控制路径:
- 通过
os.Setenv("TMPDIR", "/path/to/clean/tmp")在程序启动时指定独立临时目录,并配 crontab 定期清理 - 更稳妥的做法是绕过默认临时机制,用
multipart.NewReader手动流式解析,边读边存、不缓存整份数据(适合超大文件或敏感内容) - 永远不要信任
Filename字段 —— 它来自客户端,可能含../路径穿越,保存前必须 sanitize,例如用filepath.Base(f.Filename)
最常被跳过的一步是文件名净化,哪怕只是本地测试,也建议统一加一层白名单校验,比如只允许 [a-zA-Z0-9._-]+ 模式。









