news 2026/4/16 2:23:48

ASP.NET Core如何支持大文件上传的加密传输与国密算法集成?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ASP.NET Core如何支持大文件上传的加密传输与国密算法集成?

《政府信创项目大文件传输攻坚实录:从开源困境到自研方案的破局之路》
——北京.NET程序员的国产化适配实战

第一章:项目背景与核心挑战

作为某政府招投标项目的核心开发成员,我负责实现20GB级大文件传输系统,需满足以下严苛要求:

  1. 功能需求

    • 支持单个文件/文件夹上传下载(保留层级结构)
    • 支持断点续传、秒传(MD5校验)
    • 传输进度可视化(精确到每个子文件)
  2. 兼容性要求

    • 浏览器:IE8+、Chrome、Firefox、龙芯浏览器、红莲花浏览器、奇安信浏览器
    • 操作系统:Windows、统信UOS、中标麒麟、银河麒麟
    • 数据库:SQL Server、MySQL、Oracle、达梦、人大金仓
  3. 技术栈限制

    • 前端:Vue2 + Element UI(需兼容IE8的Polyfill方案)
    • 后端:ASP.NET Core 3.1(需适配国产中间件)
    • 存储:分布式文件系统(对接政府指定存储设备)

开源评估惨败

  • WebUploader:停更多年,IE8兼容性差,无信创浏览器支持
  • Plupload:文件夹上传需Flash(IE已淘汰),无国产化适配
  • Uppy:现代浏览器友好,但IE8直接崩溃

结论开源无解,必须自研


第二章:前端方案——Vue2的"兼容性炼金术"

1. 浏览器兼容性基座
2. 文件夹上传组件(兼容IE8+)
// src/components/FolderUploader.vueexportdefault{data(){return{files:[],isDragging:false,chunkSize:5*1024*1024// 5MB分片}},methods:{// 触发文件夹选择(IE8+兼容方案)triggerFolderInput(){if(window.FileReader&&window.File&&window.FileList&&window.Blob){// 现代浏览器使用input[type=file] webkitdirectorythis.$refs.folderInput.setAttribute('webkitdirectory','')this.$refs.folderInput.click()}else{// IE8+使用ActiveXObject(需政府环境配置权限)try{constshell=newActiveXObject('Shell.Application')constfolder=shell.BrowseForFolder(0,'请选择文件夹',0)if(folder){this.scanFolderIE(folder)}}catch(e){this.$message.error('您的浏览器不支持文件夹上传,请使用Chrome/Firefox')}}},// IE专属文件夹扫描(递归处理)scanFolderIE(folder){constfolderItems=folder.Items()for(leti=0;i<folderItems.Count;i++){constitem=folderItems.Item(i)if(item.IsFolder){this.scanFolderIE(item.GetFolder)}elseif(item.Path){this.files.push({name:item.Name,path:item.Path,size:item.Size,lastModified:item.ModifyDate})}}},// 文件分片上传(通用方案)asyncuploadFile(file){constfileId=this.calculateFileId(file)// MD5生成唯一IDconstchunks=Math.ceil(file.size/this.chunkSize)for(leti=0;i<chunks;i++){conststart=i*this.chunkSizeconstend=Math.min(file.size,start+this.chunkSize)constchunk=file.slice(start,end)constformData=newFormData()formData.append('fileId',fileId)formData.append('chunkIndex',i)formData.append('totalChunks',chunks)formData.append('chunkData',chunk)formData.append('fileName',file.name)formData.append('relativePath',file.relativePath||'')// 保留层级try{awaitaxios.post('/api/upload/chunk',formData,{onUploadProgress:(e)=>{this.updateProgress(fileId,i,chunks,e.loaded)}})}catch(e){console.error(`分片${i}上传失败`,e)throwe}}// 通知服务器合并分片awaitaxios.post('/api/upload/merge',{fileId,fileName:file.name})}}}

关键点

  • IE8兼容:通过ActiveXObject实现文件夹遍历(需政府环境开启权限)
  • 现代浏览器:使用webkitdirectory属性(Chrome/Edge)
  • 信创浏览器:通过User-Agent检测,降级为单文件上传模式

第三章:后端方案——ASP.NET Core的"分片传输引擎"

1. 分片上传控制器
// Controllers/UploadController.cs[ApiController][Route("api/[controller]")]publicclassUploadController:ControllerBase{privatereadonlyIFileStorageService_storageService;privatereadonlyIDatabaseService_dbService;// 适配多数据库// 分片上传接口[HttpPost("chunk")]publicasyncTaskUploadChunk(IFormFilechunkData,[FromForm]stringfileId,[FromForm]intchunkIndex,[FromForm]inttotalChunks){if(chunkData==null||chunkData.Length==0)returnBadRequest("无效的分片数据");// 临时存储分片(路径格式:/temp/{fileId}/{chunkIndex}.part)vartempPath=Path.Combine("temp",fileId,$"{chunkIndex}.part");Directory.CreateDirectory(Path.GetDirectoryName(tempPath));using(varstream=newFileStream(tempPath,FileMode.Create)){awaitchunkData.CopyToAsync(stream);}// 记录分片信息到数据库(达梦/人大金仓兼容)await_dbService.RecordChunk(newChunkRecord{FileId=fileId,ChunkIndex=chunkIndex,TotalChunks=totalChunks,Size=chunkData.Length,ReceivedTime=DateTime.Now});returnOk(new{success=true});}// 合并分片接口[HttpPost("merge")]publicasyncTaskMergeChunks([FromBody]MergeRequestrequest){vartempDir=Path.Combine("temp",request.FileId);if(!Directory.Exists(tempDir))returnNotFound("未找到分片数据");// 按顺序读取所有分片varchunkFiles=Directory.GetFiles(tempDir,"*.part").OrderBy(f=>int.Parse(Path.GetFileNameWithoutExtension(f))).ToList();// 最终存储路径(保留原始相对路径)varfinalPath=Path.Combine("uploads",request.RelativePath,request.FileName);Directory.CreateDirectory(Path.GetDirectoryName(finalPath));// 合并分片using(varfinalStream=newFileStream(finalPath,FileMode.Create)){foreach(varchunkFileinchunkFiles){varchunkData=awaitSystem.IO.File.ReadAllBytesAsync(chunkFile);awaitfinalStream.WriteAsync(chunkData,0,chunkData.Length);System.IO.File.Delete(chunkFile);// 删除临时分片}}// 清理空目录Directory.Delete(tempDir);// 记录完整文件信息到数据库await_dbService.RecordFinalFile(newFinalFileRecord{FileId=request.FileId,FilePath=finalPath,Size=newFileInfo(finalPath).Length,UploadTime=DateTime.Now});returnOk(new{url=$"/downloads/{finalPath}"});}}
2. 数据库适配层(抽象多数据库支持)
// Services/IDatabaseService.cspublicinterfaceIDatabaseService{TaskRecordChunk(ChunkRecordrecord);TaskRecordFinalFile(FinalFileRecordrecord);Task>GetChunks(stringfileId);}// Implementations/SqlServerDatabaseService.cspublicclassSqlServerDatabaseService:IDatabaseService{privatereadonlyApplicationDbContext_context;publicSqlServerDatabaseService(ApplicationDbContextcontext){_context=context;}publicasyncTaskRecordChunk(ChunkRecordrecord){_context.Chunks.Add(record);await_context.SaveChangesAsync();}// 其他方法实现...}// Implementations/DamengDatabaseService.cspublicclassDamengDatabaseService:IDatabaseService{privatereadonlyIDmProvider_dmProvider;// 达梦数据库专用ProviderpublicDamengDatabaseService(IDmProviderdmProvider){_dmProvider=dmProvider;}publicasyncTaskRecordChunk(ChunkRecordrecord){// 达梦数据库特有语法处理varcmd=_dmProvider.CreateCommand();cmd.CommandText="INSERT INTO CHUNK_RECORDS VALUES(...)";// ...参数绑定awaitcmd.ExecuteNonQueryAsync();}}

关键设计

  • 分片存储:临时分片按/temp/{fileId}/{index}.part组织
  • 断点续传:通过数据库记录已上传分片索引
  • 数据库适配:通过依赖注入动态切换SQL Server/达梦/人大金仓实现

第四章:信创环境适配实战

1. 操作系统兼容性处理
// Program.cs 中检测操作系统并加载对应配置publicstaticIHostBuilderCreateHostBuilder(string[]args){varisLinux=RuntimeInformation.IsOSPlatform(OSPlatform.Linux);varisKylin=File.Exists("/etc/kylin-release");// 银河麒麟检测varisUOS=File.Exists("/etc/uos-release");// 统信UOS检测returnHost.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder=>{webBuilder.UseStartup();if(isKylin||isUOS){webBuilder.UseKestrel(options=>{options.ListenAnyIP(5000,listenOptions=>{listenOptions.Protocols=HttpProtocols.Http1AndHttp2;});});}});}
2. 信创浏览器降级方案
// src/utils/browserDetect.jsexportfunctiondetectBrowser(){constua=navigator.userAgentif(ua.includes('LongArch'))return'longxin'// 龙芯浏览器if(ua.includes('RedLotus'))return'redlotus'// 红莲花浏览器if(ua.includes('QiAnXin'))return'qianxin'// 奇安信浏览器if(ua.includes('MSIE 8')||ua.includes('Trident/5'))return'ie8'return'modern'}// 在上传组件中使用constbrowserType=detectBrowser()if(browserType==='ie8'||browserType==='longxin'){// 禁用文件夹上传,显示警告this.$message.warning('当前浏览器仅支持单文件上传')}

第五章:项目成果与经验总结

1. 最终实现效果
  • 功能:20GB文件上传下载,支持文件夹层级结构
  • 兼容性
    • ✅ IE8+(需ActiveX权限)
    • ✅ 统信UOS/中标麒麟/银河麒麟
    • ✅ 龙芯/红莲花/奇安信浏览器
  • 性能:5MB分片传输,20GB文件约需4000个分片(实测3小时完成)
2. 关键决策点
  1. 放弃开源:WebUploader等组件无法满足信创要求
  2. 分片传输:解决大文件内存溢出问题
  3. 数据库抽象:通过接口隔离不同数据库实现
3. 后续优化方向
  • WebAssembly加速:用C#编写分片合并逻辑编译为WASM
  • P2P传输:在政府内网环境探索点对点加速方案

结语
在信创环境下开发大文件传输系统,就像在"带着镣铐跳舞"。但通过合理的架构设计和兼容性处理,我们最终交付了满足政府需求的稳定方案。完整代码已开源至内部GitLab(因涉密需申请访问),欢迎同行交流(可加QQ群:374992201)。

(完)
——北京政府项目组·张工

设置框架

安装.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/4/16 1:24:03

WiseAgent智能体框架实战之CrewAI篇(二) | 从零开始构建基础导诊智能体

引言 大家好&#xff0c;我是 Wise 玩转 AI。在系列文章的第一篇中&#xff0c;我们介绍了CrewAI框架的核心概念和医院导诊智能体的整体规划。今天&#xff0c;我们将开始第 1 期的工程实践&#xff0c;从零开始构建一个基础的医院导诊智能体。 第 1 期的目标是实现最基础的导…

作者头像 李华
网站建设 2026/4/15 20:53:33

程序员能做的最好的副业是什么?

像什么996&#xff0c;007这些。其最残酷的是扼杀了程序员其他的可能性&#xff0c;就是要让你只埋头干活&#xff0c;不要去思考选择其他事情。很多人都说中国的程序员是没有积累的职业&#xff0c;不像医生&#xff0c;律师&#xff0c;教师这些。❝所以我们尽早得尝试都积累…

作者头像 李华
网站建设 2026/4/15 20:52:09

基于Web的skc分类管理系统

摘 要 随着科技的发展和创新&#xff0c;让人们的生活变得更加丰富多彩&#xff0c;从人们最开始对互联网时代的怀疑到现如今越来越离不开互联网&#xff0c;无不标志着互联网的飞速发展。现如今互联网与人们日常生活相互结合&#xff0c;产生出了许多能够让人们生活效率有所…

作者头像 李华
网站建设 2026/4/15 16:54:00

最近在折腾变频器控制,发现SVPWM配合PI调节这组合真是经典永流传。今天就跟大伙唠唠实际实现中的那些门道,手头正好有些仿真和代码能拿出来掰扯

交流异步电机svpwm采用pi控制 有说明文件和仿真先说说这PI控制怎么跟SVPWM搭伙干活。异步电机那数学模型看着就头大&#xff0c;不过好在有矢量控制这神器。咱们先把三相电流咔嚓一转变成dq坐标系&#xff0c;这时候PI控制器就能在旋转坐标系里精准打击误差了。上段核心代码&am…

作者头像 李华
网站建设 2026/4/15 20:55:14

Open-AutoGLM电子病历辅助系统实战应用(医疗AI落地稀缺案例解析)

第一章&#xff1a;Open-AutoGLM电子病历辅助系统实战应用&#xff08;医疗AI落地稀缺案例解析&#xff09;在医疗AI领域&#xff0c;电子病历的智能化处理长期面临数据非结构化、术语专业性强和隐私合规要求高等挑战。Open-AutoGLM作为国内首个开源的医疗大模型辅助系统&#…

作者头像 李华
网站建设 2026/4/15 20:53:32

你真的会用Open-AutoGLM吗?:90%人忽略的流程发起关键节点解析

第一章&#xff1a;Open-AutoGLM请假流程发起的核心认知在企业级自动化办公系统中&#xff0c;Open-AutoGLM 作为基于大语言模型驱动的智能流程引擎&#xff0c;其请假流程的发起机制融合了自然语言理解与规则引擎决策能力。用户通过语义化指令即可触发结构化审批流&#xff0c…

作者头像 李华