基于Asp.Net Core WebApi能否用REST API上传50M-1G大文件?最优方案是什么?
大文件上传方案解答
普通单请求REST API上传的可行性
理论上可以通过调整ASP.NET Core的请求大小限制实现50MB-1GB文件的单请求上传,但完全不推荐生产环境用这种方案,核心问题包括:
- ASP.NET Core默认请求体大小上限仅30MB,就算修改配置突破限制,也无法解决网络波动导致的上传失败全量重传问题,1GB文件上传中断后要重新传整个文件,用户体验极差
- 单请求传输大文件会大量占用服务器内存和磁盘缓存,并发稍高就容易触发服务OOM崩溃
- 绝大多数反向代理、网关、CDN都有默认的请求超时和大小限制,大文件上传极易被中间环节中断
最优生产级方案:分片上传+断点续传
这是目前行业内大文件上传的通用成熟方案,具体实现逻辑如下:
前端实现逻辑
- 将待上传的大文件按固定大小(推荐5-20MB/片,可根据网络环境调整)切割为多个连续分片,为每个分片生成唯一标识(可采用「文件整体MD5+分片序号」的格式)
- 先发送初始化上传请求,携带文件总大小、分片总数、文件名、
fileUploaderUserId等元数据,后端校验后返回本次上传的唯一任务ID - 按顺序或并发上传每个分片,请求中携带任务ID、分片序号、分片内容
- 所有分片上传完成后,发送合并请求通知后端处理
- 上传中断后可先查询已上传分片列表,跳过已完成的分片直接续传剩余部分
后端ASP.NET Core实现逻辑
第一步:调整服务默认限制
按单分片的最大大小调整请求限制即可,不需要放开到1GB,降低服务器风险:
var builder = WebApplication.CreateBuilder(args); // 配置Kestrel最大请求体大小,按分片大小+冗余配置,比如分片设10MB就配15MB builder.WebHost.ConfigureKestrel(opt => { opt.Limits.MaxRequestBodySize = 15 * 1024 * 1024; }); // 配置表单最大大小,和上面保持一致 builder.Services.Configure<FormOptions>(opt => { opt.MultipartBodyLengthLimit = 15 * 1024 * 1024; });
第二步:数据库表调整
在原有Files表基础上,新增FileUploadTasks临时表存储上传任务信息,核心字段包括:任务ID、文件总大小、分片总数、已上传分片序号集合、文件MD5、uploadDate、fileUploaderUserId、上传状态(待上传/上传中/已完成/已失败)
第三步:接口开发
- 初始化上传接口:先校验文件MD5是否已存在于
Files表,存在直接返回已上传的文件信息(实现秒传);不存在则新建上传任务,返回任务ID - 分片上传接口:接收分片内容,按「任务ID+分片序号」命名存入临时目录,同步更新
FileUploadTasks表中已上传分片列表 - 合并接口:校验所有分片是否全部上传完成,校验通过后按分片序号拼接为完整文件,生成文件存储路径,将路径、
uploadDate、fileUploaderUserId等元数据写入Files表,删除临时分片文件,更新上传任务状态为已完成 - 可选:续传查询接口:提供任务ID查询已上传分片列表的能力,配合前端实现断点续传
额外优化建议
- 定时清理过期上传任务对应的临时分片文件,比如保留7天未完成的任务,避免磁盘空间浪费
- 每个分片上传完成后校验分片MD5,和前端上传的分片MD5比对,避免传输过程中文件损坏
Files表中存储文件相对路径即可,不要存储绝对路径,方便后续服务器迁移、存储介质更换
内容的提问来源于stack exchange,提问作者HamidrezaSh
相关产品推荐
相关产品推荐

