央企应用里,.NET Core如何处理文件夹上传的断点?
大文件上传系统开发日记2023年11月15日 项目启动客户提出了一个极具挑战性的文件传输系统需求作为山东的个人开发者这次接到的项目确实不简单。需求包含20G大文件传输、文件夹结构保持、断点续传、加密传输等多项复杂功能还要兼容IE8这种古董浏览器。今天开始记录开发过程中的关键点和解决方案。技术选型分析前端方案由于需要兼容IE8我们不得不放弃纯H5方案转而采用WebUploader作为基础。虽然项目要求原生JS实现但考虑到开发效率我们决定以WebUploader为核心进行定制开发。// 初始化WebUploader实例varuploaderWebUploader.create({auto:false,swf:Uploader.swf,// Flash文件路径用于IE兼容server:/api/upload,pick:#picker,chunked:true,chunkSize:5*1024*1024,// 分片大小5MBthreads:3,fileNumLimit:1000,fileSizeLimit:20*1024*1024*1024,// 20GBfileSingleSizeLimit:20*1024*1024*1024,duplicate:true,compress:false});文件夹上传实现WebUploader本身不支持文件夹上传我们需要通过递归遍历文件夹结构来实现// 文件夹处理函数functionhandleDirectory(files,relativePath){for(leti0;ifiles.length;i){constfilefiles[i];if(file.isDirectory){constreaderfile.createReader();reader.readEntries(entries{handleDirectory(entries,relativePathfile.name/);});}else{file.customRelativePathrelativePath;uploader.addFiles(file);}}}// 监听文件夹选择document.getElementById(folderPicker).addEventListener(change,function(e){constentriese.target.webkitEntries;if(entriesentries.length0){handleDirectory(entries);}},false);2023年11月16日 断点续传实现断点续传是项目的核心需求之一需要前后端协同设计。前端断点续传逻辑// 文件分片上传前检查是否已上传uploader.on(uploadBeforeSend,function(block,data){data.chunkblock.chunk;data.chunksblock.chunks;data.md5uploader.md5File(block.file);// 检查分片状态return$.ajax({url:/api/checkChunk,type:POST,async:false,data:{md5:data.md5,chunk:data.chunk,chunks:data.chunks,fileName:block.file.name,fileSize:block.file.size,relativePath:block.file.customRelativePath||},success:function(res){if(res.uploaded){// 该分片已上传跳过returnfalse;}}});});后端C#实现 (ASP.NET WebForm)[WebMethod]publicstaticCheckChunkResultCheckChunk(stringmd5,intchunk,intchunks,stringfileName,longfileSize,stringrelativePath){stringchunkPathPath.Combine(Server.MapPath(~/App_Data/Upload),md5);// 检查分片目录是否存在if(!Directory.Exists(chunkPath)){Directory.CreateDirectory(chunkPath);}// 检查分片文件是否存在stringchunkFilePath.Combine(chunkPath,chunk.ToString());boolexistsFile.Exists(chunkFile);returnnewCheckChunkResult{Uploadedexists,AllUploadedexistsDirectory.GetFiles(chunkPath).Lengthchunks};}2023年11月17日 加密传输实现客户要求SM4和AES加密我们决定在前端实现加密后再传输。前端加密实现// 使用CryptoJS实现AES加密functionencryptFileChunk(chunk,key){constwordArrayCryptoJS.lib.WordArray.create(chunk);constencryptedCryptoJS.AES.encrypt(wordArray,key,{mode:CryptoJS.mode.CFB,padding:CryptoJS.pad.Pkcs7});returnencrypted.toString();}// 文件分片加密处理uploader.on(uploadAccept,function(file,data){if(data.chunk){constkeysessionStorage.getItem(encryptKey)||defaultEncryptKey;return{chunkData:encryptFileChunk(data.chunkData,key),isEncrypted:true};}returndata;});后端解密处理[WebMethod]publicstaticvoidUploadChunk(stringmd5,intchunk,intchunks,stringfileName,longfileSize,stringrelativePath,stringchunkData,boolisEncrypted){stringchunkPathPath.Combine(Server.MapPath(~/App_Data/Upload),md5);stringchunkFilePath.Combine(chunkPath,chunk.ToString());byte[]dataConvert.FromBase64String(chunkData);if(isEncrypted){// 解密处理dataAESHelper.Decrypt(data,ConfigurationManager.AppSettings[EncryptKey]);}File.WriteAllBytes(chunkFile,data);// 检查是否所有分片都已上传if(Directory.GetFiles(chunkPath).Lengthchunks){MergeFiles(md5,fileName,fileSize,relativePath);}}2023年11月18日 文件夹结构保持保持文件夹层级结构是项目的另一个挑战我们需要在前后端协同处理路径信息。前端路径处理// 文件添加到队列时记录相对路径uploader.on(fileQueued,function(file){file.relativePathfile.customRelativePath||;});后端C#路径处理privatestaticvoidMergeFiles(stringmd5,stringfileName,longfileSize,stringrelativePath){stringchunkPathPath.Combine(Server.MapPath(~/App_Data/Upload),md5);string[]chunkFilesDirectory.GetFiles(chunkPath).OrderBy(fint.Parse(Path.GetFileName(f))).ToArray();// 确保目标目录存在stringdestDirectoryPath.Combine(Server.MapPath(~/Uploads),Path.GetDirectoryName(relativePath));if(!Directory.Exists(destDirectory)){Directory.CreateDirectory(destDirectory);}stringdestFilePath.Combine(destDirectory,fileName);using(FileStreamfsnewFileStream(destFile,FileMode.Create,FileAccess.Write)){foreach(stringchunkFileinchunkFiles){byte[]bufferFile.ReadAllBytes(chunkFile);fs.Write(buffer,0,buffer.Length);}}// 上传到阿里云OSSUploadToOSS(destFile,Path.Combine(relativePath,fileName));// 清理临时文件Directory.Delete(chunkPath,true);}2023年11月19日 IE8兼容方案为了兼容IE8我们需要引入Flash后备方案和polyfill。IE8检测和兼容处理// 检测IE版本functiongetIEVersion(){varuawindow.navigator.userAgent;varmsieua.indexOf(MSIE );if(msie0){returnparseInt(ua.substring(msie5,ua.indexOf(.,msie)),10);}returnfalse;}// 根据浏览器选择上传方式if(getIEVersion()getIEVersion()8){// IE8及以下使用Flash上传uploader.options.server/api/upload_flash;uploader.options.forceFlashtrue;}else{// 现代浏览器使用HTML5上传uploader.options.server/api/upload_html5;uploader.options.forceFlashfalse;}后端Flash上传处理[WebMethod]publicstaticvoidUploadFlash(){HttpPostedFilefileHttpContext.Current.Request.Files[0];stringfileNameHttpContext.Current.Request[name];stringrelativePathHttpContext.Current.Request[relativePath]??;stringmd5HttpContext.Current.Request[md5];// 处理文件保存逻辑stringdestDirectoryPath.Combine(Server.MapPath(~/Uploads),relativePath);if(!Directory.Exists(destDirectory)){Directory.CreateDirectory(destDirectory);}stringdestFilePath.Combine(destDirectory,fileName);file.SaveAs(destFile);// 上传到阿里云OSSUploadToOSS(destFile,Path.Combine(relativePath,fileName));}2023年11月20日 阿里云OSS集成我们需要将最终文件存储到阿里云OSS实现加密存储。C# OSS上传实现privatestaticvoidUploadToOSS(stringlocalFilePath,stringossPath){stringendpointConfigurationManager.AppSettings[OSSEndpoint];stringaccessKeyIdConfigurationManager.AppSettings[OSSAccessKeyId];stringaccessKeySecretConfigurationManager.AppSettings[OSSAccessKeySecret];stringbucketNameConfigurationManager.AppSettings[OSSBucketName];OssClientclientnewOssClient(endpoint,accessKeyId,accessKeySecret);try{// 读取文件内容byte[]fileContentFile.ReadAllBytes(localFilePath);// 加密存储if(ConfigurationManager.AppSettings[EncryptStorage]true){fileContentAESHelper.Encrypt(fileContent,ConfigurationManager.AppSettings[StorageEncryptKey]);}// 上传到OSSMemoryStreamstreamnewMemoryStream(fileContent);client.PutObject(bucketName,ossPath,stream);}catch(Exceptionex){// 记录错误日志LogError(OSS上传失败: ex.Message);throw;}}2023年11月21日 文件夹下载功能客户要求文件夹下载不打包我们需要实现保持目录结构的下载方式。前端文件夹下载请求functiondownloadFolder(folderPath){// 获取文件夹内容列表$.ajax({url:/api/listFolder,type:POST,data:{folderPath:folderPath},success:function(files){// 逐个创建下载链接files.forEach(file{constadocument.createElement(a);a.href/api/download?filePath${encodeURIComponent(file.path)};a.downloadfile.name;a.style.displaynone;document.body.appendChild(a);a.click();document.body.removeChild(a);});}});}后端文件夹列表和下载[WebMethod]publicstaticListListFolder(stringfolderPath){stringphysicalPathPath.Combine(Server.MapPath(~/Uploads),folderPath);varfilesnewList();if(Directory.Exists(physicalPath)){foreach(stringfileinDirectory.GetFiles(physicalPath,*,SearchOption.AllDirectories)){files.Add(newFileInfo{pathfile.Substring(Server.MapPath(~/Uploads).Length).Replace(\\,/).TrimStart(/),namePath.GetFileName(file),sizenewFileInfo(file).Length});}}returnfiles;}[WebMethod]publicstaticvoidDownload(stringfilePath){stringphysicalPathPath.Combine(Server.MapPath(~/Uploads),filePath);if(File.Exists(physicalPath)){byte[]fileBytesFile.ReadAllBytes(physicalPath);// 解密存储的文件if(ConfigurationManager.AppSettings[EncryptStorage]true){fileBytesAESHelper.Decrypt(fileBytes,ConfigurationManager.AppSettings[StorageEncryptKey]);}HttpContext.Current.Response.ContentTypeapplication/octet-stream;HttpContext.Current.Response.AddHeader(Content-Disposition,$attachment; filename\{Path.GetFileName(filePath)}\);HttpContext.Current.Response.BinaryWrite(fileBytes);HttpContext.Current.Response.End();}else{HttpContext.Current.Response.StatusCode404;}}项目总结这个项目确实极具挑战性特别是需要兼容IE8的同时还要实现20G大文件上传和文件夹结构保持。通过本次开发我总结了以下经验分片上传是大文件传输的关键需要合理设置分片大小断点续传依赖于文件唯一标识(MD5)和分片状态记录文件夹结构保持需要在前后端协同处理相对路径IE8兼容需要使用Flash后备方案加密传输应该在前端完成减少敏感数据暴露完整的项目代码和文档已经整理完毕欢迎同行在QQ群(374992201)交流讨论。期待与更多开发者合作共同承接更多优质项目。设置框架安装.NET Framework 4.7.2https://dotnet.microsoft.com/en-us/download/dotnet-framework/net472框架选择4.7.2添加3rd引用编译项目NOSQLNOSQL无需任何配置可直接访问页面进行测试SQL使用IIS大文件上传测试推荐使用IIS以获取更高性能。使用IIS Express小文件上传测试可以使用IIS Express创建数据库配置数据库连接信息检查数据库配置访问页面进行测试相关参考文件保存位置效果预览文件上传文件刷新续传支持离线保存文件进度在关闭浏览器刷新浏览器后进行不丢失仍然能够继续上传文件夹上传支持上传文件夹并保留层级结构同样支持进度信息离线保存刷新页面关闭页面重启系统不丢失上传进度。下载完整示例下载完整示例

相关新闻

汽车制造企业如何选择PPT转存插件?

汽车制造企业如何选择PPT转存插件?

【程序员老王的暴富日记】 各位前端战友们好!我是安徽那个天天被甲方爸爸逼着改需求的秃头前端老王,最近接了个CMS官网项目,甲方提出了个"既要马儿跑又要马儿不吃草"的神奇需求——要在UEditor里实现Word/Excel/PPT/PDF全格式导入…

2026/5/17 7:11:51 阅读更多 →
大模型AI算法高薪职业,风口,但是一定是对所有人的风口吗

大模型AI算法高薪职业,风口,但是一定是对所有人的风口吗

THE LAST TIME 现在AI频频抢占人们眼球。在求职中经常在网上看到,有人拿到AI算法offer,年包将近上百万。都在吹嘘风口,不入行就赶不上,这样的话术。 但是这AI算法风口真的对我们所有人都是风口吗? 大家求职的时候&…

2026/7/5 5:03:16 阅读更多 →
毕业论文神器!继续教育专属AI论文网站 —— 千笔

毕业论文神器!继续教育专属AI论文网站 —— 千笔

你是否曾为论文选题发愁,反复修改却总对表达不满意?是否在深夜面对空白文档无从下笔,又担心查重率过高?论文写作的每一步都充满挑战,尤其是对于继续教育的学生来说,时间紧、任务重,更需要高效可…

2026/7/4 23:13:18 阅读更多 →

最新新闻

Git 功能发展历史

Git 功能发展历史

目录 Git 的诞生与设计哲学2005—2008:从原型到 1.0 的奠基期Git 1.5—1.9:基础功能完善期Git 2.0:里程碑式的行为变更Git 2.1—2.22:渐进式改进与体验优化Git 2.23:switch 与 restore 的引入Git 2.24—2.29&#xff…

2026/7/5 5:49:45 阅读更多 →
终极解决方案:KMS智能激活脚本完整指南 - 彻底告别Windows和Office激活烦恼

终极解决方案:KMS智能激活脚本完整指南 - 彻底告别Windows和Office激活烦恼

终极解决方案:KMS智能激活脚本完整指南 - 彻底告别Windows和Office激活烦恼 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 还在为Windows系统频繁弹出激活提示而烦恼吗?…

2026/7/5 5:47:45 阅读更多 →
受够了记账 App 的广告和会员,我自己写了一个:完全免费、数据 100% 在本地、开源

受够了记账 App 的广告和会员,我自己写了一个:完全免费、数据 100% 在本地、开源

受够了记账 App 的广告和会员,我自己写了一个:完全免费、数据 100% 在本地、开源 先说结论:这是一个没有广告、没有会员、没有内购、不需要注册、不联网上传任何数据的记账 App。代码开源在 GitHub,Android 安装包直接从 Release…

2026/7/5 5:45:44 阅读更多 →
PyInstaller 打包 exe 图标不显示问题(AI生成)

PyInstaller 打包 exe 图标不显示问题(AI生成)

# PyInstaller 打包 exe 图标不显示?这篇文章帮你彻底解决!## 🔍 问题背景最近在用 PyInstaller 打包一个 PySide6 项目时,遇到了一个非常头疼的问题:**设置了图标但 exe 文件始终不显示**。经过一番折腾,终…

2026/7/5 5:45:44 阅读更多 →
知网查重太贵?2026年免费论文查重渠道汇总+PaperRed隐藏功能曝光

知网查重太贵?2026年免费论文查重渠道汇总+PaperRed隐藏功能曝光

2026年毕业季,知网查重一次要多少钱?答案是:本科论文约100-200元,硕博论文200-400元。而且很多学校只给1-2次免费查重机会,用完之后就得自费。对于预算有限的学生来说,这笔开销不算小。更让人头疼的是&…

2026/7/5 5:43:44 阅读更多 →
电机控制进阶——PID速度环参数整定实战与调优

电机控制进阶——PID速度环参数整定实战与调优

1. PID速度环控制基础概念 第一次接触电机PID控制时,我盯着那三条看似简单的曲线发愣——比例、积分、微分,这三个数学概念怎么就能让电机转速乖乖听话呢?后来在实验室熬了三个通宵才明白,PID控制就像教小朋友骑自行车&#xff1a…

2026/7/5 5:41:44 阅读更多 →

日新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

月新闻