必须提前调用 http.Request.ParseMultipartForm,否则 r.MultipartForm 为 nil 或 r.FormFile 返回 http.ErrNotMultipart;ParseForm 对 multipart 无效,仅处理 application/x-www-form-urlencoded。

Go 的 http.Request.ParseMultipartForm 必须提前调用
不调用 ParseMultipartForm 就直接读 r.MultipartForm 或用 r.FormFile,会返回 nil 或 http.ErrNotMultipart。这不是 bug,是 Go 的显式设计:它把解析延迟到你明确需要时,避免无意义的内存开销。
常见错误是只写 r.ParseForm() —— 这对 multipart 表单完全无效,ParseForm 只处理 application/x-www-form-urlencoded。
- 必须在读取文件前调用
r.ParseMultipartForm(maxMemory),maxMemory单位是字节,建议设为 32 - 若不确定大小,可设为
0,但注意这会让所有文件都落地到磁盘,失去内存缓冲优势 - 调用后,
r.MultipartForm.File才有数据,r.FormValue才能取到同表单里的普通字段
r.FormFile 和 r.MultipartForm.File 的区别与选法
r.FormFile("name") 是快捷封装,内部会自动触发一次 ParseMultipartForm(32 (如果还没解析过),并返回第一个同名文件。它适合简单场景,但隐含行为容易掩盖问题。
r.MultipartForm.File["name"] 是原始 map,需要你确保已调用 ParseMultipartForm,且能拿到全部同名文件(比如前端用了 multiple)。
立即学习“go语言免费学习笔记(深入)”;
大小仅1兆左右 ,足够轻便的商城系统; 易部署,上传空间即可用,安全,稳定; 容易操作,登陆后台就可设置装饰网站; 并且使用异步技术处理网站数据,表现更具美感。 前台呈现页面,兼容主流浏览器,DIV+CSS页面设计; 如果您有一定的网页设计基础,还可以进行简易的样式修改,二次开发, 发布新样式,调整网站结构,只需修改css目录中的css.css文件即可。 商城网站完全独立,网站源码随时可供您下载
- 上传单文件、逻辑简单 → 用
r.FormFile更省事 - 需校验多个同名文件、或想统一控制解析参数(如不同接口用不同
maxMemory)→ 手动调用ParseMultipartForm后查MultipartForm.File - 注意:
r.FormFile返回的*multipart.FileHeader不是文件内容,只是元信息;要读内容得再调file.Open()
保存文件时务必检查 FileHeader.Size 和 FileHeader.Header.Get("Content-Type")
前端可以伪造 name 和 Content-Type,不验证就直接保存,轻则存错类型,重则触发路径遍历或执行恶意文件。
- 用
filepath.Base(fh.Filename)提取原始文件名,避免../../etc/passwd类路径穿越 - 用
fh.Size做前置大小限制(比如 >100MB 直接http.Error),别等io.Copy到一半才失败 -
fh.Header.Get("Content-Type")可信度低,真正校验要用net/http.DetectContentType读前 512 字节,或更稳妥地用filetype库做二进制魔数识别 - 生成服务端文件名时,不要拼接原始名,用
uuid.New().String() + ext更安全
大文件上传需配合客户端分片或服务端流式处理
默认情况下,ParseMultipartForm 会把整个文件(或其内存部分)加载进进程内存,上传 1GB 文件可能导致 OOM。Go 标准库不支持原生断点续传或分片合并。
- 若必须支持大文件,推荐客户端分片(如使用
uppy或dropzone),服务端只接收单片、校验md5/sha256并暂存,最后由合并接口拼接 - 若坚持单请求上传,可用
r.Body直接读流:跳过ParseMultipartForm,用multipart.NewReader(r.Body, boundary)边读边存,绕过内存限制,但需手动解析 boundary 和 header - 注意:Nginx 默认
client_max_body_size 1m,Go 服务能接,但反向代理可能先拦住,需同步调大
文件上传看着简单,但边界情况多在解析时机、大小控制、类型校验和反向代理配置上,漏掉任意一环都可能变成线上事故。









