当前位置: 首页 > news >正文

ASP.NET Core如何优化大文件上传的性能?

政府招投标项目大文件传输解决方案探索

作为山东济南一家软件公司项目负责人,近期我们正全身心投入一个政府招投标项目。在项目推进过程中,大文件传输需求成为了一大关键挑战,必须找到一套契合项目各方面要求的解决方案。

一、项目需求剖析

(一)文件传输规模与功能

本次项目要求支持 50G 左右的大文件传输,涵盖文件和文件夹的上传与下载功能。尤为关键的是,文件夹传输时需完整保留其层级结构,确保数据的完整性和准确性。

(二)信创国产化适配

由于是政府项目,信息安全至关重要,必须全面支持信创国产化环境。具体包括:

  1. 操作系统:统信 UOS、中标麒麟、银河麒麟。
  2. 浏览器:主流浏览器以及信创国产浏览器,如龙芯浏览器、红莲花浏览器、奇安信安全浏览器。
  3. 数据库:主流的 SQL Server、MySQL、Oracle 以及国产化的达梦、人大金仓。

(三)技术架构与部署

后端采用.NET Core 技术栈,前端基于 vue2 - cli 框架。项目部署于内网环境,需支持私有部署,以保障数据的安全性和隐私性。

(四)授权与成本考量

公司客户主要集中在政府和军工单位,考虑到项目数量众多,每年约 2000 + 个,单套授权方式不仅成本高昂,而且管理繁琐。因此,领导决定采购产品源代码,由公司研发部门自主负责后续开发与维护,同时满足产品部门的自研需求。

二、开源组件调研困境

在项目初期,我们对市场上的开源组件进行了广泛调研,但结果不尽如人意。以百度开源的大文件上传组件 WebUploader 为例,该组件目前已经停止更新,缺乏技术支持。我们曾尝试联系开发人员,但发出的消息一个多月都未得到任何回应。其他开源组件也存在类似问题,没有可靠的技术支持渠道,一旦遇到问题无法及时联系到作者解决,这给项目的顺利推进带来了极大风险,因此我们决定重新寻找更合适的解决方案。

三、解决方案探索与部分代码实现

(一)整体架构设计思路

考虑到项目需求和技术栈,我们计划基于.NET Core 和 vue2 - cli 构建一套自定义的大文件传输解决方案。后端负责文件分片处理、存储管理以及与数据库的交互;前端实现文件分片上传、下载以及进度显示等功能。

(二)后端实现(.NET Core)

1. 文件分片接收与合并
usingMicrosoft.AspNetCore.Mvc;usingSystem.IO;[ApiController][Route("api/[controller]")]publicclassFileUploadController:ControllerBase{privatereadonlystring_uploadFolder="Uploads";publicFileUploadController(){if(!Directory.Exists(_uploadFolder)){Directory.CreateDirectory(_uploadFolder);}}[HttpPost("upload")]publicIActionResultUpload([FromForm]FileUploadModelmodel){stringfilePath=Path.Combine(_uploadFolder,model.FileName);stringtempFilePath=filePath+".tmp";// 如果是第一个分片,创建临时文件;否则追加到临时文件if(model.ChunkIndex==0){using(varfileStream=newFileStream(tempFilePath,FileMode.Create)){fileStream.Write(model.FileData,0,model.FileData.Length);}}else{using(varfileStream=newFileStream(tempFilePath,FileMode.Append)){fileStream.Write(model.FileData,0,model.FileData.Length);}}// 如果是最后一个分片,将临时文件重命名为正式文件if(model.IsLastChunk){System.IO.File.Move(tempFilePath,filePath);returnOk(new{message="File uploaded successfully"});}returnOk(new{message="Chunk uploaded successfully"});}}publicclassFileUploadModel{publicstringFileName{get;set;}publicbyte[]FileData{get;set;}publicintChunkIndex{get;set;}publicboolIsLastChunk{get;set;}}
2. 数据库记录文件信息
usingMicrosoft.EntityFrameworkCore;publicclassFileContext:DbContext{publicDbSetFiles{get;set;}publicFileContext(DbContextOptionsoptions):base(options){}}publicclassFileInfo{publicintId{get;set;}publicstringFileName{get;set;}publicstringFilePath{get;set;}publiclongFileSize{get;set;}// 其他文件相关信息字段}

在项目启动时,根据配置的数据库类型(SQL Server、MySQL、Oracle、达梦、人大金仓),配置相应的数据库连接字符串和 EF Core 提供程序。例如,对于 MySQL 数据库:

// 在 Program.cs 中配置 MySQL 数据库连接varbuilder=WebApplication.CreateBuilder(args);// 添加 MySQL EF Core 提供程序builder.Services.AddDbContext(options=>options.UseMySql(builder.Configuration.GetConnectionString("MySQLConnection"),ServerVersion.AutoDetect(builder.Configuration.GetConnectionString("MySQLConnection"))));

(三)前端实现(vue2 - cli)

1. 文件分片上传组件
export default { data() { return { selectedFiles: [], uploadProgress: 0 }; }, methods: { handleFileChange(event) { this.selectedFiles = Array.from(event.target.files); }, async uploadFiles() { for (const file of this.selectedFiles) { const chunkSize = 5 * 1024 * 1024; // 5MB 分片大小 const totalChunks = Math.ceil(file.size / chunkSize); let uploadedChunks = 0; for (let i = 0; i < totalChunks; i++) { const start = i * chunkSize; const end = Math.min(start + chunkSize, file.size); const chunk = file.slice(start, end); const formData = new FormData(); formData.append('FileName', file.name); formData.append('FileData', chunk); formData.append('ChunkIndex', i); formData.append('IsLastChunk', i === totalChunks - 1); try { await this.$http.post('/api/fileupload/upload', formData, { onUploadProgress: (progressEvent) => { uploadedChunks++; this.uploadProgress = Math.round((uploadedChunks / totalChunks) * 100); } }); } catch (error) { console.error('上传分片失败:', error); break; } } } } } };
2. 文件夹层级结构处理

在前端,当用户选择文件夹上传时,需要通过递归的方式遍历文件夹中的所有文件和子文件夹,并为每个文件生成相对路径,以便在传输到后端后能够恢复文件夹的层级结构。

functiontraverseFolder(entry,relativePath=''){returnnewPromise((resolve,reject)=>{constresults=[];if(entry.isFile){entry.file(file=>{// 这里可以对文件进行一些处理,比如设置文件的相对路径file.relativePath=relativePath+file.name;results.push(file);resolve(results);});}elseif(entry.isDirectory){constdirReader=entry.createReader();dirReader.readEntries(entries=>{constpromises=[];for(constsubEntryofentries){constnewRelativePath=relativePath+entry.name+'/';promises.push(traverseFolder(subEntry,newRelativePath));}Promise.all(promises).then(subResults=>{subResults.forEach(subResult=>{results.push(...subResult);});resolve(results);}).catch(reject);},reject);}});}

handleFileChange方法中调用traverseFolder方法来处理文件夹上传:

handleFileChange(event){constfiles=Array.from(event.target.files);constfolderPromises=[];for(constfileoffiles){if(file.webkitRelativePath){// 如果是文件夹中的文件,通过 webkitRelativePath 获取相对路径信息// 这里可以进一步优化处理文件夹层级结构的逻辑constentry={isFile:true,file:(callback)=>{callback(file);}};// 简单模拟,实际需要根据 webkitRelativePath 构建更完整的层级结构处理file.relativePath=file.webkitRelativePath;}else{// 如果是单独的文件,直接处理continue;}}// 更完整的文件夹处理示例if(files.length>0&&files[0].webkitGetAsEntry){constentry=files[0].webkitGetAsEntry();if(entry&&entry.isDirectory){traverseFolder(entry).then(folderFiles=>{this.selectedFiles=this.selectedFiles.concat(folderFiles);});}}},

四、后续计划与展望

目前,我们已经完成了大文件传输解决方案的基本架构设计和部分代码实现。接下来,我们将重点进行以下工作:

  1. 全面测试:在不同信创国产化操作系统和浏览器上进行全面测试,确保文件传输功能的稳定性和兼容性。
  2. 性能优化:对大文件传输过程进行性能优化,提高传输速度和效率,减少传输时间。
  3. 安全加固:加强信息安全防护,对文件传输过程进行加密处理,防止数据泄露。
  4. 完善功能:根据项目实际需求,进一步完善文件夹层级结构处理、文件管理等功能。

通过本次探索和实现,我们有信心为政府招投标项目提供一套满足各方面要求的大文件传输解决方案,为公司赢得更多项目机会,同时也为信创国产化在软件领域的应用贡献一份力量。

设置框架

安装.NET Framework 4.7.2
https://dotnet.microsoft.com/en-us/download/dotnet-framework/net472
框架选择4.7.2

添加3rd引用

编译项目

NOSQL

NOSQL无需任何配置可直接访问页面进行测试

SQL

使用IIS
大文件上传测试推荐使用IIS以获取更高性能。

使用IIS Express

小文件上传测试可以使用IIS Express

创建数据库

配置数据库连接信息

检查数据库配置

访问页面进行测试


相关参考:
文件保存位置,

效果预览

文件上传

文件刷新续传

支持离线保存文件进度,在关闭浏览器,刷新浏览器后进行不丢失,仍然能够继续上传

文件夹上传

支持上传文件夹并保留层级结构,同样支持进度信息离线保存,刷新页面,关闭页面,重启系统不丢失上传进度。

批量下载

支持文件批量下载

下载续传

文件下载支持离线保存进度信息,刷新页面,关闭页面,重启系统均不会丢失进度信息。

文件夹下载

支持下载文件夹,并保留层级结构,不打包,不占用服务器资源。

下载完整示例

下载完整示例

http://www.jsqmd.com/news/73428/

相关文章:

  • 【收藏必备】手摸手带你搞定RAG:大模型检索增强生成实战教程
  • C#如何实现大文件上传的权限控制?
  • 日期题模版(made by yyf)
  • 【活动总结】创药沙龙第一期:ADC药物研发的挑战与机遇成功举办
  • 【C/C++】多继承以及继承过程的注意事项
  • CppCon 2024 学习:Gazing Beyond Reflection for C++26
  • 【MCP SC-400安全加固黄金法则】:3年实战经验浓缩的7项配置规范
  • android studio 2025 2.2版本 需要点击Main menu才会出现工具栏?如何默认显示工具栏?
  • xshell的一个会话的连接的ip地址在哪里修改?
  • Day9 >> 151、反转字符串中的单词 +
  • 2025中国电缆一线品牌推荐,中国电缆十大品牌推荐:知名品牌12月TOP榜单 - 品牌2026
  • 三星三折叠价格和功能揭秘:19999元起,三折叠旗舰藏多少惊喜?
  • K8S系列之6.1:自定义扩展(CRD 与 Operator 设计模式)
  • R-Zero:从零数据自进化推理大语言模型
  • 基于密集型复杂城市场景下求解无人机三维路径规划的Q-learning 算法研究(Matlab代码实现)
  • 如何用免费工具3分钟终极优化Windows右键菜单:告别杂乱,提升300%操作效率
  • Wan2.2-T2V-A14B在地震波传播模拟教学中的科学准确性
  • Day25
  • Actor-Critic 强化学习中的两大核心损失函数:PG Loss 与 VF Loss 详解
  • Wan2.2-T2V-A14B能否生成符合人类视觉习惯的景深效果
  • Wan2.2-T2V-A14B在环保公益广告创作中的社会责任体现
  • Day 36 MLP神经网络的训练
  • 终极指南:5分钟掌握XUnity.AutoTranslator让外文游戏变中文
  • Wan2.2-T2V-A14B能否识别并生成特定艺术风格如水彩画
  • 2025 最新跨境物流服务商 / 公司 TOP5 评测!深度覆盖欧美加专线,全链路方案 + 时效保障权威榜单发布,赋能跨境电商高效发展 - 全局中转站
  • 基于Comsol的激光熔覆熔池流动数值模拟探索
  • 中国台湾阳明交大团队让AI帮你实现真正的冻结时光
  • 金融机构如何落地智能体?16个头部企业Agent最佳实践
  • 超细整理,性能测试如何做?怎么做?性能压力负载(汇总二)
  • 工作生活没有节奏感怎么办?