应调用ctx.FormFiles("files")获取文件头切片,验证大小和MIME(需魔数校验),清理文件名后保存,出错时用ctx.StopWithStatus(400)终止请求。

Controller里怎么读取多个上传文件
iris的MVC控制器不自动解析multipart/form-data,必须手动调用ctx.FormFile()或ctx.FormFiles()。前者只取第一个同名文件,后者返回[]*multipart.FileHeader切片——这才是处理多文件的正确入口。
常见错误是直接写c.Ctx.FormValue("files"),这永远返回空字符串,因为文件字段没有文本值。
- 用
ctx.FormFiles("files")获取全部文件头(注意字段名必须和HTML表单中name="files"一致) - 检查返回切片长度是否为0,避免空上传时panic
- 每个
*multipart.FileHeader包含Filename、Size、Header等元信息,但不含内容
怎么验证文件类型和大小
验证必须在打开文件前完成,否则可能因恶意超大文件耗尽内存或触发OOM。iris不提供内置校验器,得自己写逻辑。
- 先遍历
fileHeaders,对每个fh.Size做上限判断(比如单文件≤10MB) - 用
fh.Header.Get("Content-Type")取MIME类型,但不可信——攻击者可伪造,必须配合bytes读前几个字节比对魔数 - 推荐用
github.com/h2non/filetype库:调用filetype.MatchReader(file, &limitReader),它能安全识别PNG/JPEG/PDF等50+格式 - 拒绝
application/octet-stream或空MIME的文件,除非业务明确允许二进制上传
保存文件时要注意路径和并发安全
iris的ctx.SaveFormFile()只是包装了os.Create + io.Copy,不处理目录创建、重名覆盖或并发写冲突。
- 目标路径必须提前
os.MkdirAll(dir, 0755),否则SaveFormFile会报no such file or directory - 不要直接用
fh.Filename作保存名——它可能含../路径穿越或特殊字符,需用path.Base()截取并strings.ReplaceAll()清理 - 高并发场景下,多个请求同时写同一目录易触发
too many open files,建议用sync.Pool复用*os.File或改用异步队列 - 生产环境务必限制总上传数(如最多5个),防止
FormFiles()吃光内存
为什么用StopWithStatus而不是Return
iris MVC控制器方法执行完自动返回,但文件读取和保存是阻塞IO,若中间出错不显式中断,后续代码仍会执行——比如错误日志写了两遍,或重复调用数据库。
- 验证失败时必须立刻调用
ctx.StatusCode(400)+ctx.JSON(BizError{...})+ctx.StopWithStatus(400) -
StopWithStatus会终止当前请求生命周期,跳过所有后续中间件和控制器逻辑 - 漏掉
return语句会导致ctx.JSON()后继续执行,可能panic(如访问已关闭的文件句柄) - 别用
panic(&BizError{...})处理文件错误——recover中间件无法区分业务错误和IO panic,日志会混乱
context.WithTimeout,iris默认不干预这一层。


















