beego 文件上传需用 getfile 获取 *multipart.fileheader 的 filename 字段得原始名,savetofile 前须用 os.mkdirall 创建目录、避免路径遍历,且需调大 maxmemory 和 maxuploadsize 防止大文件失败。

Beego 的文件上传不靠自己解析 multipart/form-data,而是用封装好的 GetFile + SaveToFile 组合,原始文件名默认可直接拿到,但必须注意路径构造、临时文件清理和并发写入风险。
如何用 GetFile 正确获取原始文件名
GetFile 返回三个值:文件句柄、*multipart.FileHeader 和错误。真正带原始名的是第二个参数的 Filename 字段——它来自 HTTP 请求头中的 Content-Disposition,不是客户端路径或伪造名。
- 浏览器上传时,
header.Filename是用户选中文件的真实名称(如report.pdf),不含本地完整路径 - 若用 curl 或 Postman 手动构造请求,
Filename可被任意设置,需校验合法性(比如过滤../、空格、控制字符) - 不要用
filepath.Base(header.Filename)再处理——header.Filename本身已是纯净文件名
SaveToFile 的路径参数陷阱
SaveToFile 第二个参数是“保存路径+文件名”,Beego 不会自动创建父目录;如果 static/upload/ 不存在,会直接 panic 或静默失败(取决于 Go 版本和系统权限)。
- 务必提前用
os.MkdirAll("static/upload", 0755)创建目录,且放在Post()方法开头 - 路径不能以
/开头(如/tmp/file.jpg),否则可能写到根目录甚至被拒绝 - 避免拼接用户输入的完整路径:
"static/upload/" + header.Filename有路径遍历风险;应只取后缀并重命名,例如:"static/upload/" + fmt.Sprintf("%d_%s", time.Now().UnixNano(), filepath.Base(header.Filename))
大文件上传前必须调大 MaxMemory 和 MaxUploadSize
Beego 默认把 ≤64MB 的文件全读进内存,超限则转临时磁盘文件;但若 MaxUploadSize 设得太小(比如默认 0),大文件会被直接拦截,返回 413 状态码。
- 在
main.go初始化处设置:web.MaxMemory = 1 ,<code>web.MaxUploadSize = 1 - 或在
conf/app.conf中配:maxmemory = 67108864,maxuploadsize = 1073741824 - 注意:两个值要合理搭配——
MaxMemory应 ≤MaxUploadSize,否则中间态行为不可控
上传后不 defer file.Close() 会泄漏文件句柄
GetFile 返回的 file 是一个 io.ReadCloser,底层可能是内存 buffer 或临时文件。不显式关闭会导致 fd 泄漏,尤其高并发时很快耗尽系统资源。
- 必须在
GetFile后立刻加defer file.Close(),哪怕后续没用到file数据 - 如果要用该句柄做流式处理(如上传到七牛云),
Close()必须等流传输完成后再调用,不能 defer 在开头 - 常见错误写法:
if err != nil { return }前没 close,导致 error 分支跳过关闭逻辑
原始文件名看着简单,但拼路径、控大小、关句柄这三步漏掉任何一环,上线后就会卡在奇怪的地方——比如上传成功却找不到文件、并发上传时覆盖彼此、或者跑两天就报 “too many open files”。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











