必须显式启用 iris.MultipartForm 中间件,否则 FormFile 始终返回 nil;单文件用 ctx.FormFile() 并检查 error 后再 Open,多文件用 ctx.UploadForm();保存前需创建目录、净化文件名、限制请求体大小。

文件上传必须显式启用 multipart 解析器
Iris 默认不解析 multipart/form-data 请求体,哪怕前端已正确设置 enctype="multipart/form-data",ctx.FormFile() 或 ctx.UploadForm() 也会返回空或报错。必须在启动前调用 app.ConfigureContainer 或直接注册解析器。
推荐做法是在 main() 中添加:
app.Use(iris.Compression) // 必须加这一行,否则 FormFile 始终 nil app.Use(iris.MultipartForm)
注意:iris.MultipartForm 是中间件,不是配置项;漏掉它,后续所有文件操作都失效。
Controller 中读取单个/多个文件的写法差异
Iris 的 FormFile 和 UploadForm 行为不同,选错会导致 panic 或静默失败:
-
ctx.FormFile("avatar"):只取第一个同名文件,返回*multipart.FileHeader和error,适合单文件上传 -
ctx.UploadForm():返回完整map[string][]*multipart.FileHeader,适合多文件(如photos[])或不确定数量的场景 - 不要对
FormFile结果直接.Open()—— 必须先检查 error,否则 nil pointer panic
示例(安全读取单文件):
func (c *UploadController) Post(ctx iris.Context) {
fileHeader, err := ctx.FormFile("file")
if err != nil {
ctx.StatusCode(400)
ctx.JSON(zerr.BizError{Code: 40003, Msg: "未找到上传文件"})
return
}
src, err := fileHeader.Open()
if err != nil {
ctx.StatusCode(500)
ctx.JSON(zerr.BizError{Code: 50003, Msg: "打开文件失败"})
return
}
defer src.Close()
// 后续保存逻辑...
}
保存文件时路径、权限和大小限制必须手动控制
Iris 不提供自动存储或安全校验,所有边界条件都要自己处理:
- 目标路径需提前
os.MkdirAll("./uploads", 0755),否则os.Create报no such file or directory - 文件名不能直接用
fileHeader.Filename—— 它来自客户端,可能含../或空字节,必须 sanitize(例如用path.Base()+ UUID 重命名) - 必须限制大小,否则攻击者可传超大文件耗尽内存:
ctx.SetMaxRequestBodySize(10 (10MB)要放在 <code>app.Use()链中,且必须早于iris.MultipartForm
常见错误:把 SetMaxRequestBodySize 放在 Use(MultipartForm) 之后 → 限制不生效。
上传成功后返回 JSON 而不是重定向
MVC Controller 方法若返回 string 或结构体,Iris 会自动 JSON 序列化并设 200 OK;但如果你手动调用了 ctx.JSON(),就不要再 return 任何值,否则响应体重复或状态码错乱。
正确模式是二选一:
- 纯返回值方式(推荐):
return map[string]string{"url": "/uploads/" + newFilename},框架自动设200并 JSON 化 - 手动控制方式:
ctx.StatusCode(201)+ctx.JSON(...)+return,缺一不可
容易被忽略的点:上传接口常需 201 Created,但 Iris 不会因返回结构体自动改状态码 —— 必须显式调用 ctx.StatusCode()。


















