ASP.NET Core文件上传优化方案:大文件上传、分片上传与断点续传完整实现指南
2026-07-26 125 0
在企业系统、网盘应用、视频平台以及后台管理系统中,文件上传一直是比较常见的功能。当用户上传几百 MB 甚至几个 GB 的文件时,传统的 ASP.NET Core 文件上传方式容易遇到超时、内存占用过高、网络中断导致重新上传等问题。
一个优秀的大文件上传方案通常需要支持文件分片上传、断点续传、上传进度显示以及失败自动恢复等功能。本文将介绍如何基于 ASP.NET Core 实现一套可靠的大文件上传方案。
ASP.NET Core 官方支持普通文件上传和流式上传两种方式。对于较小文件,可以使用 IFormFile 简化处理;而对于大文件场景,更推荐使用 Streaming 方式减少服务器内存压力。
为什么普通文件上传不适合大文件场景
很多开发者刚开始实现上传功能时,会直接使用 IFormFile:
[HttpPost("upload")]
public async Task<IActionResult> Upload(IFormFile file)
{
var filePath = Path.Combine("uploads", file.FileName);
using var stream = new FileStream(filePath, FileMode.Create);
await file.CopyToAsync(stream);
return Ok();
}
这种方式对于图片、文档等小文件没有问题,但是面对大文件时会存在几个明显问题。
- 首先,服务器需要处理完整文件请求。如果多个用户同时上传大文件,会增加服务器内存和磁盘临时空间压力。
- 其次,网络不稳定时,如果上传到 90% 失败,用户只能重新上传整个文件,体验非常差。
- 另外,大文件上传过程中无法方便实现暂停、继续上传以及上传进度控制。
ASP.NET Core 文档也指出,大文件上传场景应该避免大量缓冲文件,而应该采用流式处理方式降低资源消耗。
大文件上传优化方案设计
一个完整的大文件上传系统通常包含以下几个步骤:
1. 文件切片
客户端首先将大文件拆分成多个小文件块。例如一个 1GB 文件:
文件大小:1024MB
分片大小:10MB
最终生成:
chunk_001
chunk_002
chunk_003
...
chunk_102
每个分片独立上传。
这样做的好处:
- 单次请求数据量较小
- 网络失败只需要重新上传失败分片
- 可以实现多个分片并行上传
- 支持暂停和恢复
目前很多网盘、云存储服务都采用类似方案。
2. 上传文件初始化
上传之前,客户端需要告诉服务器文件信息。
例如:
{
"fileName": "video.mp4",
"fileSize": 1073741824,
"chunkSize": 10485760,
"chunkCount": 103
}
服务器根据这些信息创建上传任务。
可以生成一个唯一 UploadId:a81f2c7e-9d55-4e7b,后续所有分片上传都通过这个 ID 关联。
数据库可以保存:
| 字段 | 说明 |
|---|---|
| UploadId | 上传任务ID |
| FileName | 文件名称 |
| FileSize | 文件大小 |
| ChunkCount | 分片数量 |
| UploadedChunks | 已上传分片 |
ASP.NET Core实现分片上传接口
创建上传接口:
[HttpPost("chunk")]
public async Task<IActionResult> UploadChunk(
IFormFile chunk,
string uploadId,
int chunkIndex)
{
var folder = Path.Combine(
"uploads",
uploadId
);
if (!Directory.Exists(folder))
{
Directory.CreateDirectory(folder);
}
var filePath = Path.Combine(
folder,
$"{chunkIndex}.chunk"
);
using var stream =
new FileStream(filePath, FileMode.Create);
await chunk.CopyToAsync(stream);
return Ok(new
{
success = true,
chunkIndex
});
}
上传后的目录结构:
uploads
└── a81f2c7e
├──0.chunk
├──1.chunk
├──2.chunk
└──3.chunk
每个分片独立保存。
实现断点续传功能
断点续传的核心是服务器知道哪些分片已经上传完成。
例如:
文件总分片:
0 1 2 3 4 5 6
服务器已有:
0 1 2 4
需要继续上传:
3 5 6
客户端上传前请求:GET /upload/status?id=xxxx
服务器返回:
{
"uploadedChunks":[0,1,2,4]
}
前端收到后跳过已有分片。
这样即使浏览器关闭,再次打开上传页面,也可以继续上传。
文件合并处理
所有分片上传完成后,需要合并文件。ASP.NET Core 可以使用 FileStream 顺序读取:
public async Task MergeFile(
string uploadId,
string fileName,
int chunkCount)
{
var target =
Path.Combine(
"uploads",
fileName);
using var output =
new FileStream(
target,
FileMode.Create);
for(int i = 0; i < chunkCount; i++)
{
var chunkPath =
Path.Combine(
"uploads",
uploadId,
$"{i}.chunk");
using var input =
new FileStream(
chunkPath,
FileMode.Open);
await input.CopyToAsync(output);
}
}
合并完成:
0.chunk
1.chunk
2.chunk
3.chunk
↓
video.mp4
之后可以删除临时分片文件释放空间。
增加文件秒传功能
如果希望进一步优化上传体验,可以增加秒传功能。
实现方式:上传前计算文件 Hash。开始上传后,服务器查询数据库是否存在相同Hash。如果存在,直接返回上传成功,无需再次传输文件。
这种方式特别适合企业网盘、资源管理系统。
优化上传性能技巧
使用并发上传
不用等待分片逐个完成,可以同时上传多个分片,提高网络利用率。
使用流式写入
对于超大文件,不建议一次读取全部内容。
推荐:
await stream.CopyToAsync(fileStream);
避免:
byte[] buffer = File.ReadAllBytes();
否则可能导致服务器内存快速增长。
使用对象存储
生产环境中,不建议所有文件都存储在 Web 服务器本地。
可以考虑:
- Azure Blob Storage
- Amazon S3
- 阿里云 OSS
- 腾讯云 COS
这些服务本身针对大文件上传进行了优化。
大文件上传安全注意事项
文件上传接口必须做好安全处理。
常见措施包括:
1. 限制文件大小
services.Configure<FormOptions>(options =>
{
options.MultipartBodyLengthLimit =
1024 * 1024 * 1024;
});
2. 限制文件类型
例如:
允许:
.mp4
.jpg
.pdf
禁止:
.exe
.dll
3. 不要直接使用用户上传的文件名
- 上传目录禁止执行权限
- 对文件进行病毒扫描
- 检查文件真实 MIME 类型
ASP.NET Core 官方也建议对上传文件进行验证,并避免直接信任用户提供的文件名。
总结
ASP.NET Core 实现大文件上传时,简单使用 IFormFile 只能满足基础需求。如果面对视频、压缩包、安装包等大文件场景,更推荐采用分片上传 + 断点续传方案。
完整的大文件上传流程通常包括:文件切片、上传任务管理、分片保存、断点检测、文件合并以及安全验证。通过这种设计,可以有效解决大文件上传失败、服务器压力过高以及用户体验差等问题,同时也为后续扩展秒传、多线程上传、对象存储提供基础。
对于需要处理大量文件的 ASP.NET Core 项目,例如企业网盘、CMS系统、在线教育平台,这套方案具有较高的实用价值。