央企应用里,.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 阅读更多 →

最新新闻

Python社交网络分析:从脏数据清洗到图构建的七道硬核工序

Python社交网络分析:从脏数据清洗到图构建的七道硬核工序

1. 这不是“画个关系图”就完事的——为什么用Python做社交网络分析,90%的人连数据清洗这关都过不去“Social Network Analysis in Python”这个标题听起来很学术、很技术,但如果你真把它当成一门“学几个networkx函数就能发论文”的速成课,那…

2026/7/5 7:02:00 阅读更多 →
5分钟快速上手:Parsec VDD虚拟显示器完全指南

5分钟快速上手:Parsec VDD虚拟显示器完全指南

5分钟快速上手:Parsec VDD虚拟显示器完全指南 【免费下载链接】parsec-vdd ✨ Perfect virtual display for game streaming 项目地址: https://gitcode.com/gh_mirrors/pa/parsec-vdd 你是否曾经因为缺少物理显示器而无法充分利用远程服务器?或者…

2026/7/5 6:59:59 阅读更多 →
基于WebGPU与WASM的本地AI图像修复与超分工具Inpaint-Web部署与实战

基于WebGPU与WASM的本地AI图像修复与超分工具Inpaint-Web部署与实战

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度 在实际图像处理工作中,我们经常遇到两类棘手问题:一是从网络获取的图片分辨率过低,放大后细节模糊…

2026/7/5 6:57:59 阅读更多 →
Python图像隐写术:用位操作实现LSB信息隐藏

Python图像隐写术:用位操作实现LSB信息隐藏

1. 项目概述:用Python的“像素画笔”藏匿秘密如果你对编程感兴趣,尤其是用Python处理过图片,那你一定知道PIL或Pillow库,它们能让你轻松地读取像素、修改颜色。但你是否想过,一张看似普通的风景照、一张可爱的表情包&a…

2026/7/5 6:55:58 阅读更多 →
3个痛点,1个方案:Wand-Enhancer如何彻底改变你的游戏修改体验

3个痛点,1个方案:Wand-Enhancer如何彻底改变你的游戏修改体验

3个痛点,1个方案:Wand-Enhancer如何彻底改变你的游戏修改体验 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/gh_mirrors/we/Wand-Enhancer 你是否曾经为游戏修…

2026/7/5 6:53:58 阅读更多 →
WarcraftHelper:魔兽争霸III终极性能优化与兼容性解决方案

WarcraftHelper:魔兽争霸III终极性能优化与兼容性解决方案

WarcraftHelper:魔兽争霸III终极性能优化与兼容性解决方案 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper WarcraftHelper是一款专为《魔兽…

2026/7/5 6:49:57 阅读更多 →

日新闻

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 阅读更多 →

月新闻