asp.net core 中用 iformfile 接收上传文件最直接:参数声明为 iformfile(单文件)或 iformfilecollection(多文件),匹配前端 input 的 name 属性,禁用 [frombody],校验文件合法性并流式保存。

ASP.NET Core 中用 IFormFile 接收上传文件最直接
HTTP 文件上传在 ASP.NET Core 中默认走表单 multipart/form-data,后端不用手动解析原始流——框架已封装好。核心是用 IFormFile 类型绑定上传的单个文件,它自带 FileName、ContentType、Length 和 OpenReadStream() 等关键属性和方法。
常见错误是直接用 string 或 byte[] 去绑定上传字段,这会导致模型绑定失败,请求体被丢弃,返回 400 或空值。
- 控制器方法参数必须声明为
IFormFile(单文件)或IFormFileCollection(多文件) - 前端
<input type="file">的name属性值需与参数名一致,例如<input name="file">对应[FromForm] IFormFile file - 不要在参数上加
[FromBody],multipart 数据不走 JSON 解析管道 - 若用 Swagger 测试,需在
Startup.cs或Program.cs中启用AddControllersWithViews()并确保EnableRequestSizeLimit足够大(默认仅 128MB)
大文件上传必须配置 RequestSizeLimit 和 DisableRequestSizeLimit
ASP.NET Core 默认限制整个请求体大小为 128MB,超过会直接返回 404.13(Request Entity Too Large)。这不是业务逻辑能捕获的异常,而是在中间件早期就被拦截了。
两种处理方式:
- 对特定 Action 放宽限制:在 Controller 方法上加
[RequestSizeLimit(500_000_000)](单位字节) - 彻底禁用限制(仅限可信内网场景):加
[DisableRequestSizeLimit],但必须配合反向代理(如 Nginx)的client_max_body_size设置,否则仍会失败 - 全局修改需在
WebHostBuilder阶段调用UseKestrel(o => o.Limits.MaxRequestBodySize = null),但不推荐
注意:MaxRequestBodySize = null 表示不限制,但 Kestrel 实际仍有底层 socket 缓冲区约束,超大文件仍建议分块上传。
部分功能简介:商品收藏夹功能热门商品最新商品分级价格功能自选风格打印结算页面内部短信箱商品评论增加上一商品,下一商品功能增强商家提示功能友情链接用户在线统计用户来访统计用户来访信息用户积分功能广告设置用户组分类邮件系统后台实现更新用户数据系统图片设置模板管理CSS风格管理申诉内容过滤功能用户注册过滤特征字符IP库管理及来访限制及管理压缩,恢复,备份数据库功能上传文件管理商品类别管理商品添加/修改/
保存文件前务必校验 file.Length 和 file.FileName
IFormFile 不代表文件一定存在或合法。用户可能提交空文件、恶意扩展名、路径遍历字符串(如 ../../web.config),或伪造 Content-Type。
- 先检查
file.Length == 0,跳过空上传 - 用
Path.GetExtension(file.FileName)提取扩展名,白名单比对(如只允许.pdf、.jpg),别信file.ContentType - 用
Path.GetFileName(file.FileName)获取干净文件名,避免目录穿越 - 生成唯一文件名(如
Guid.NewGuid() + ext),防止覆盖或竞态写入 - 写入磁盘前确保目标目录存在且进程有写权限,否则抛
UnauthorizedAccessException
流式保存比 CopyToAsync 更适合大文件和内存敏感场景
IFormFile.CopyToAsync(Stream) 是最常用方式,但它会把整个文件读进内存再刷出,对 >100MB 的文件容易触发 GC 压力甚至 OutOfMemoryException。
更稳妥的做法是手动控制流:
using var stream = file.OpenReadStream(); using var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 81920, useAsync: true); await stream.CopyToAsync(fs);
关键点:
- 显式指定
bufferSize(如 80KB),避免默认 8KB 在高吞吐下频繁调度 -
useAsync: true启用真正的异步 I/O,避免线程池阻塞 - 不要用
file.CopyTo()(同步版),它在高并发时会快速耗尽线程池 - 若需病毒扫描或内容校验,应在流复制过程中逐块处理,而非全量加载
真正难的不是“怎么传”,而是上传中途断连、重复提交、临时文件清理、存储一致性这些边界问题——它们不会出现在 Hello World 示例里,但上线后第一个凌晨报警往往就来自这儿。









