Beego 中 GetFile 仅获取单个文件,多文件必须用 GetFiles;GetFiles 返回文件头列表,需遍历调用 fh.Open() 和 io.Copy 保存,注意路径安全与资源释放,MaxUploadSize 限制总大小。

Beego 中 GetFile 只能取单个文件,多文件得用 GetFiles
Beego 的 GetFile 方法签名是 func (c *Controller) GetFile(name string) (file multipart.File, fh *multipart.FileHeader, err error),它只接收一个 name 字段名,对应 HTML 表单里单个 <input type="file" name="avatar">。如果你写了多个同名 input(比如 name="files"),或者前端用了 multiple 属性(<input type="file" name="files" multiple>),GetFile 仍然只返回第一个文件 —— 这是常见误解的根源。
真正支持多文件的是 GetFiles,它返回 []*multipart.FileHeader,每个元素都带原始文件名、大小、MIME 类型等信息。你必须用它配合循环处理,而不是反复调 GetFile。
-
GetFile("files")→ 永远只拿到第一个文件,其余丢弃 -
GetFiles("files")→ 拿到全部上传的文件头列表,可遍历 - 前端
<input name="files" multiple>和后端GetFiles("files")必须 name 严格一致
保存多文件时,SaveToFile 不适用,得手动 Open + Copy
SaveToFile 是为单文件设计的:它内部调用 GetFile 再写入磁盘,不接受文件头切片。想存多个文件,必须自己打开每个 FileHeader 对应的文件流,再复制到目标路径。
关键点在于:FileHeader 本身不是文件句柄,它只是元数据;要读内容,得用 c.Request.MultipartReader() 或更直接的方式 —— Beego 控制器提供了 c.GetFile 的变体能力,但对多文件,推荐用 fh.Open() 获取可读流:
- 对每个
*multipart.FileHeader,调fh.Open()得到multipart.File - 用
io.Copy把流写入os.Create(dstPath)创建的目标文件 - 务必
defer file.Close()和dst.Close(),否则句柄泄漏 - 别直接拼接用户传来的
fh.Filename作路径,需清洗(如过滤../、控制扩展名)
MaxUploadSize 限制的是所有文件总大小,不是单个
Beego 的 MaxUploadSize 配置项(可通过 web.MaxUploadSize = 10 设置)作用于整个 HTTP 请求体,即所有上传文件加起来不能超过该值。比如设为 <code>10MB,那么 5 个 2.1MB 的文件就会被整体拒绝,返回 413 Payload Too Large。
这和 MaxMemory(默认 64MB)不同:MaxMemory 控制内存缓存阈值,影响是否落盘;而 MaxUploadSize 是硬性门限,超了请求根本进不到控制器逻辑。
- 检查配置是否生效:在
main.go初始化后设置,或在conf/app.conf加maxuploadsize = 10485760 - 前端可先用 JS 校验单个文件大小,但服务端校验不可省 —— 用户可绕过 JS
- 如果需要单独限制单文件大小,得在控制器里遍历
GetFiles结果,手动比对fh.Size
原始文件名保留靠 fh.Filename,但要注意编码和安全
Beego 的 *multipart.FileHeader 已经解析并解码了原始文件名(包括 UTF-8 中文名),所以直接用 fh.Filename 就行,不用自己 parse Content-Disposition header。但有三个现实问题常被忽略:
- Windows 上传的文件名可能含
\或冒号:,Linux 下无法创建,需替换为下划线或删除 - 攻击者可能传
../../../etc/passwd这类路径穿越名,必须用path.Base(fh.Filename)截取纯文件名 - 同名文件会覆盖,生产环境建议加时间戳或 UUID 前缀,例如
fmt.Sprintf("%s_%s", uuid.NewString(), path.Base(fh.Filename))
最简清洗示例:cleanName := path.Base(filepath.Clean(fh.Filename)),再校验长度和字符集。


















