c.formfile仅返回multipart.fileheader元数据,需显式调用file.open()获取io.readcloser,且须defer f.close()防句柄泄漏;多文件时form.file["key"]是[]multipart.fileheader切片,各元素均需单独open()。

c.FormFile 只拿元信息,不读文件内容
Fiber 的 c.FormFile("key") 返回的是 *multipart.FileHeader,只包含文件名、大小、头信息等元数据,**不是文件内容本身**。常见错误是拿到 file 就以为可以读了,结果 file.Open() 都没调,返回空或 panic。
- 必须显式调用
file.Open()才能获取可读的io.ReadCloser - 记得
defer f.Close(),否则句柄泄漏、后续上传失败 - 如果用
c.MultipartForm()解析多文件,form.File["key"]是[]*multipart.FileHeader切片,每个都要单独Open() -
c.FormFile仅在Content-Type: multipart/form-data且已调用c.ParseMultipartForm(32 后才有效;没解析就调,返回 <code>nil
POST 表单必须先 ParseMultipartForm,不能跳过
Fiber 不会自动解析 multipart 请求体,和 net/http 不同——你得自己触发解析。漏掉这步,c.FormFile 和 c.FormValue 全部返回空,且无报错提示,极难排查。
- 推荐在 handler 开头统一调:
if err := c.ParseMultipartForm(32 32 是 32MB 内存缓冲上限,超出部分会写临时磁盘;太小导致大文件上传失败,太大浪费内存- 一旦调过
c.Body()或c.BodyBytes(),再调ParseMultipartForm会静默失败(底层 fasthttp 缓冲已消耗) - 不要混用:
c.FormValue("name")和c.FormFile("avatar")必须在同一个解析上下文里取
上传到 MinIO 或本地磁盘前,务必校验文件类型和大小
直接把用户上传的原始文件丢进存储服务,等于敞开攻击面。Fiber 本身不提供校验逻辑,得你自己加。
- 用
file.Header.Size做大小限制(注意:前端传的 Content-Length 可伪造,以实际解析后的file.Size为准) - 用
f, _ := file.Open(); defer f.Close()后读前 512 字节,传给http.DetectContentType()做 MIME 类型检测,别信file.Header.Header.Get("Content-Type") - 白名单控制类型:比如只允许
"image/jpeg","image/png",拒绝"application/octet-stream"等泛类型 - 保存时重命名文件名(去掉路径、特殊字符),避免目录穿越或覆盖系统文件
多文件上传要遍历 form.File,不是 c.FormFile
c.FormFile("images") 只能取第一个同名文件;真正处理多文件(如 <input type="file" name="images" multiple>)必须用 c.MultipartForm()。
-
form, err := c.MultipartForm()返回*multipart.Form,其form.File是 map[string][]*multipart.FileHeader - 遍历:
for _, headers := range form.File["images"] { file, _ := headers.Open(); ... } - 每个
headers都要单独Open()和Close(),不能共用一个句柄 - 并发上传多个文件时,别在 goroutine 里直接传
c——c是复用对象,可能已被归还池中
最常被忽略的是:c.ParseMultipartForm 的调用时机和 c.Body() 的互斥性。很多问题不是框架 bug,而是缓冲区被提前消费后,解析函数静默失效。动手前先确认请求体是否“干净”。











