应使用IFormFile[]或IEnumerable接收多文件,确保前端name与后端参数名一致,避免手动索引、错误集合类型及重复OpenReadStream,注意文件名安全、临时文件冲突和流生命周期管理。

ASP.NET Core 里 IFormFile 多文件上传怎么接
直接用 IFormFile 数组或 IEnumerable 接收,别用单个 IFormFile 然后循环读——那是错的,会丢文件。
常见错误现象:Request.Form.Files.Count 是 0,或者只拿到第一个文件;后台断点发现 files 是空集合,但前端明明传了 3 张图。
- 确保前端
的name和后端参数名完全一致(大小写敏感) - 不要在控制器方法里写
var file = Request.Form.Files[0]—— 这只取第一个,且绕过模型绑定,files参数根本没被赋值 - 如果用
[FromForm]模型接收,模型属性必须是IEnumerable或IFormFile[],不能是List(默认不支持) - 上传大文件时,记得配
MaxRequestBodySize和UploadReadBufferSize,否则请求直接 400 或 413
FileStream 写入磁盘前必须检查 file.Length
很多同学直接 file.OpenReadStream() 然后往 FileStream 里写,结果遇到空文件或“无法读取已关闭的流”——因为 IFormFile 的流是一次性的,且可能长度为 0。
- 先判断
if (file.Length == 0),跳过或报错,别硬读 - 不要重复调用
OpenReadStream():第二次调用会返回空流或抛ObjectDisposedException - 写磁盘时建议用
using var stream = file.OpenReadStream();+await stream.CopyToAsync(fileStream),别手动Read/Write循环 - 注意路径安全:别直接拼
Path.Combine(uploadDir, file.FileName),要清理文件名(比如用Path.GetInvalidFileNameChars()过滤)
前端 FormData 多图上传的坑
用 JS 传多图时,FormData.append("files", file) 调用多次,后端才能收到多个 IFormFile。如果只 append 一次、传数组,后端收不到。
- 错误写法:
formData.append("files", fileArray)—— 这会把整个数组当一个 blob,后端只收到一个“[object File]”字符串 - 正确写法:遍历
input.files,对每个file单独append("files", file)(name 必须相同) - 如果用
fetch,别设Content-Typeheader —— 浏览器会自动设multipart/form-data并带上 boundary,手动设反而破坏格式 - 调试时看 Network → Payload → Form Data,确认每个文件都作为独立条目出现,而不是包在一个字段里
并发上传多张图时临时文件冲突
默认情况下,Kestrel 会把上传的文件暂存在系统临时目录,多个请求同时上传同名文件(比如都叫 1.jpg),可能互相覆盖或删错——这不是你代码的 bug,是中间件行为。
- 别依赖
file.FileName直接存盘,永远生成唯一文件名(如Guid.NewGuid() + Path.GetExtension(file.FileName)) - 如果用
WebHost.CreateDefaultBuilder(),临时目录由System.IO.Path.GetTempPath()决定,不可控;可改用内存流(file.CopyToAsync(memoryStream))避免落盘 - 上传完成后,临时文件由 ASP.NET Core 自动清理,但清理时机不保证立即,所以不要在上传中途去
File.Delete临时路径 - 高并发场景下,更稳妥的是全程走内存流 + 异步写入对象存储(如 Azure Blob / MinIO),绕过本地临时目录
真正麻烦的不是怎么传,而是怎么让每张图都不丢、不错、不撞、不被恶意覆盖——名字、流生命周期、临时路径、边界处理,漏一个就出问题。











