news 2026/1/10 12:28:18

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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

创建数据库

配置数据库连接信息

检查数据库配置

访问页面进行测试


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

效果预览

文件上传

文件刷新续传

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

文件夹上传

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

批量下载

支持文件批量下载

下载续传

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

文件夹下载

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

下载完整示例

下载完整示例

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/7 19:29:37

系统提示找不到msvcp140_codecvt_ids.dll文件 无法运行程序 下载修复

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

作者头像 李华
网站建设 2026/1/1 14:58:44

超细整理,性能测试如何做?怎么做?性能压力负载(汇总二)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 性能测试结果分析…

作者头像 李华
网站建设 2025/12/25 16:08:15

C++的第十四天笔记

存储持续性、作用域和链接性C使用三种&#xff08;C11四种&#xff09;不同方案存储数据。这些方案的区别在于数据保留在内存中的时间。自动存储持续性&#xff1a;在函数定义中声明的变量&#xff08;包括函数参数&#xff09;&#xff0c;程序执行所属函数 / 代码块时创建&am…

作者头像 李华
网站建设 2025/12/12 0:13:52

874-LangChain框架Use-Cases - 基于智能体的动态槽位填充系统 - 案例分析

1. 案例目标 本案例旨在构建一个基于智能体的动态槽位填充系统&#xff0c;实现智能对话系统&#xff0c;能够分析用户请求并自动收集必要信息&#xff0c;通过对话补充缺失信息。 系统主要实现以下目标&#xff1a; 实现动态槽位填充功能&#xff0c;自动识别并收集必要信息…

作者头像 李华
网站建设 2025/12/12 0:13:39

ops-nn算子库生态纵览 - 构建健壮的AI算力基石

目录 &#x1f3af; 摘要 1. ops-nn&#xff1a;CANN神经网络计算的中枢神经系统 1.1 &#x1f504; 算子库的定位与演进轨迹 1.2 &#x1f4ca; 矩阵计算&#xff1a;AI算力的本质洞察 2. NPU硬件架构&#xff1a;算子设计的物理基础 2.1 &#x1f527; AI Core微架构深…

作者头像 李华