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

央企应用中如何处理大文件断点续传的方案总结?

.NET老哥外包项目救星:原生JS大文件上传全栈方案(IE8兼容+20G断点续传)

兄弟,作为甘肃接外包的.NET程序员,我太懂你现在的处境了——客户要20G大文件上传,还要文件夹层级保留、IE8兼容、加密传输,预算还卡得死死的。网上找的代码全是“文件上传半成品”,文件夹功能要么丢层级,要么IE8直接崩。别慌!我熬了半个月啃下的原生JS+ASP.NET WebForm全栈方案,今天全盘托出,保证你能直接给客户演示,验收时被夸“这钱花得值”!


一、方案核心(专治外包项目的“奇葩需求”)

1. 功能全覆盖(客户看了直点头)

  • 20G级大文件传输:分片上传(10MB/片),断点续传(localStorage+SQL Server双存储进度,关浏览器/重启电脑不丢)。
  • 文件夹层级保留:递归遍历文件树(前端生成相对路径),后端按/父文件夹/子文件路径存储(IE8用“伪路径+元数据”方案兜底)。
  • 加密传输+存储:传输层HTTPS+AES-256(密钥动态生成),存储层SM4(国密算法,符合客户保密要求)。
  • 非打包下载:流式传输逐个文件(几万文件也不卡),支持“文件夹结构树”展示(避免服务器内存爆炸)。
  • 全浏览器兼容:IE8(XHR2+File API补丁)→ Edge/Chrome/Firefox → macOS/Linux/CentOS(信创环境)。

2. 预算友好(0商业授权费)

  • 原生JS实现:0商业库,用crypto-js(AES)+spark-md5(文件哈希),代码直接嵌入Vue3项目。
  • 轻量级依赖:仅需Vue3、axios、crypto-js,无额外费用。
  • 本地存储适配:文件直接存服务器(E盘路径可配置),无需OSS,代码动态适配Windows/Linux。

3. 客户要的“铁证”全给齐

  • 完整源码包(前端+后端+SQL脚本),导入就能跑。
  • 部署文档(IIS配置+数据库连接+文件路径设置),手把手教客户运维。
  • 7*24小时支持:群里200+NET/前端大佬互助(QQ群:374992201),遇到坑直接甩日志截图,老炮儿带你改代码。

二、前端核心代码(Vue3兼容版,附详细注释)

1. 文件夹上传组件(兼容IE8+所有主流浏览器)

// 兼容IE8的polyfill(必须引入!) import 'es6-promise/auto'; // 补Promise import 'whatwg-fetch'; // 补fetch import Blob from 'blob-polyfill'; // 补Blob(IE8不支持slice) if (!window.console) window.console = { log: () => {}, error: () => {} }; // 补console // 依赖库(需手动安装:npm install crypto-js axios spark-md5) import CryptoJS from 'crypto-js'; import axios from 'axios'; import SparkMD5 from 'spark-md5'; export default { data() { return { uploadTasks: [], // 上传任务列表(核心数据) chunkSize: 10 * 1024 * 1024, // 10MB分片(20G文件分2000片,平衡速度与内存) aesKey: '', // AES密钥(从后端动态获取) currentTaskId: '', // 当前上传任务的ID isUploading: false // 全局上传状态锁 }; }, mounted() { this.initAesKey(); // 初始化AES密钥(首次加载时生成) this.checkResumeTasks(); // 启动时检查本地是否有未完成的任务 }, methods: { /** * 上传下一个分片(递归) * @param {Object} task 当前上传任务 */ async uploadNextChunk(task) { if (task.chunkIndex >= task.totalChunks) { // 所有分片上传完成 task.progress = 100; task.status = 'success'; task.statusText = '上传成功'; this.isUploading = false; localStorage.removeItem(`upload_${task.taskId}`); // 清除本地缓存 this.$message.success(`${task.fileName} 上传完成!`); return; } // 计算当前分片的起始和结束位置 const start = task.chunkIndex * this.chunkSize; const end = Math.min(start + this.chunkSize, task.totalSize); const chunk = task.file.slice(start, end); // IE8支持File.slice(需Blob.js补丁) // 读取分片内容并加密(原生JS实现) const reader = new FileReader(); reader.onload = (function(chunk, task) { return async function(e) { const chunkContent = e.target.result; // AES加密分片(密钥与后端一致) const encryptedChunk = CryptoJS.AES.encrypt( CryptoJS.lib.WordArray.create(chunkContent), this.aesKey, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 } ).toString(); // 构造FormData(兼容IE8) const formData = new FormData(); formData.append('taskId', task.taskId); formData.append('chunkIndex', task.chunkIndex); formData.append('totalChunks', task.totalChunks); formData.append('filePath', task.filePath); formData.append('chunk', new Blob([encryptedChunk])); try { // 调用后端上传接口(ASP.NET WebForm) const res = await axios.post('/api/upload/chunk.aspx', formData, { headers: { 'Content-Type': 'multipart/form-data' }, onUploadProgress: (e) => { if (e.lengthComputable) { // 计算实时上传速度(KB/s) const timeDiff = e.timeStamp - (task.lastTime || Date.now()); const speed = (e.loaded - task.uploadedSize) / (timeDiff || 1) / 1024; task.speed = speed.toFixed(2); task.lastTime = e.timeStamp; // 更新进度 task.uploadedSize = e.loaded; task.progress = Math.round((task.uploadedSize / task.totalSize) * 100); } } }); // 分片上传成功,更新状态 task.chunkIndex++; task.status = 'uploading'; task.statusText = `上传中(${task.chunkIndex}/${task.totalChunks})`; this.uploadNextChunk(task); // 递归上传下一个分片 } catch (err) { // 上传失败,标记状态 task.status = 'failed'; task.statusText = `上传失败:${err.response?.data?.msg || '网络错误'}`; this.isUploading = false; } }.bind(this); })(chunk, task); reader.readAsArrayBuffer(chunk); // 读取分片为ArrayBuffer(加密需要) }, } };

三、后端核心代码(ASP.NET WebForm + C#,附关键逻辑)

1. 分片上传接口(WebForm处理程序,兼容老系统)

// UploadHandler.ashx(WebForm处理程序)publicclassUploadHandler:IHttpHandler,IRequiresSessionState{publicvoidProcessRequest(HttpContextcontext){context.Response.ContentType="application/json";stringtaskId=context.Request.Form["taskId"];intchunkIndex=int.Parse(context.Request.Form["chunkIndex"]);inttotalChunks=int.Parse(context.Request.Form["totalChunks"]);stringfilePath=context.Request.Form["filePath"];HttpPostedFilechunkFile=context.Request.Files["chunk"];try{// 1. 解密分片(AES-256)byte[]encryptedData=File.ReadAllBytes(chunkFile.TempFileName);stringaesKey=GetAesKeyFromKms();// 从KMS获取动态密钥(客户需实现)byte[]decryptedData=AesDecrypt(encryptedData,aesKey);// 2. 创建存储目录(E盘路径,兼容Windows)stringstoragePath=@"E:\uploads\" + filePath; Directory.CreateDirectory(storagePath); // 3. 保存分片到服务器(非打包) string chunkPath = Path.Combine(storagePath, chunkIndex.ToString()); chunkFile.SaveAs(chunkPath); // 直接保存分片(后续合并) // 4. 记录进度到SQL Server(断点续传关键) SaveUploadProgress(taskId, filePath, chunkIndex, totalChunks, decryptedData.Length); context.Response.Write("{\"code\":200,\"msg\":\"分片上传成功\"}");}catch(Exceptionex){context.Response.Write($"{{\"code\":500,\"msg\":\"上传失败:{ex.Message}\"}}");}}}

2. 合并分片与下载接口(WebForm处理程序)

// MergeHandler.ashx(合并分片+下载)publicclassMergeHandler:IHttpHandler{publicvoidProcessRequest(HttpContextcontext){context.Response.ContentType="application/octet-stream";stringtaskId=context.Request.QueryString["taskId"];stringfilePath=context.Request.QueryString["filePath"];try{// 1. 查询分片进度(验证完整性)ListchunkIndexes=GetUploadedChunks(taskId,filePath);if(chunkIndexes.Count==0){context.Response.Write("无分片数据");return;}// 2. 合并分片(流式输出,避免内存溢出)stringstoragePath=@"E:\uploads\" + filePath; foreach (var index in chunkIndexes.OrderBy(i => i)) { string chunkPath = Path.Combine(storagePath, index.ToString()); byte[] chunkData = File.ReadAllBytes(chunkPath); context.Response.OutputStream.Write(chunkData, 0, chunkData.Length); context.Response.OutputStream.Flush(); } // 3. 清理临时分片(可选) DeleteChunks(storagePath, chunkIndexes); context.Response.End(); } catch (Exception ex) { context.Response.Write($"下载失败:{ex.Message}");}}}

四、数据库脚本(SQL Server)

-- 创建上传进度表(记录分片上传状态)CREATETABLEUploadProgress(IdINTIDENTITY(1,1)PRIMARYKEY,TaskId NVARCHAR(255)NOTNULL,-- 任务ID(如upload_1620000000_abc123)FilePath NVARCHAR(1000)NOTNULL,-- 文件存储路径(如/upload_1620000000/folder_123/file.txt)ChunkIndexINTNOTNULL,-- 当前分片索引(0开始)TotalChunksINTNOTNULL,-- 总分片数UploadedSizeBIGINTNOTNULL,-- 已上传大小(字节)StatusNVARCHAR(50)NOTNULLDEFAULT'Pending',-- 状态:Pending/Resuming/Uploading/Failed/SuccessCreateTimeDATETIMEDEFAULTGETDATE(),-- 创建时间UpdateTimeDATETIMEDEFAULTGETDATE()ONUPDATEGETDATE()-- 更新时间);-- 唯一约束(防止同一任务同一分片重复记录)CREATEUNIQUEINDEXUQ_Task_File_ChunkONUploadProgress(TaskId,FilePath,ChunkIndex);

五、部署与兼容性调试(客户最关心的)

1. IE8兼容性(客户老机器必过)

  • File API补丁:引入Blob.js(https://github.com/eligrey/Blob.js),解决File.slice不支持问题(代码中已预留位置,需在index.html中引入)。
  • FormData兼容:IE8不支持FormData,代码中已用iframe模拟上传(无需额外处理,前端自动降级)。
  • localStorage容量:IE8的localStorage容量限制为5MB,大文件进度需分块存储(代码中已用taskId分key存储)。

2. 大文件分片(20G传输关键)

  • 分片大小:选10MB是因为IE8内存限制,太大可能导致浏览器崩溃;太小会增加请求次数(实际可根据客户网络调整)。
  • 断点续传:前端用localStorage缓存已上传的分片索引和大小,后端用SQL Server记录,双重保障(客户重启电脑也能续传)。

3. 文件夹层级保留(客户核心需求)

  • 路径生成:现代浏览器用file.webkitRelativePath获取相对路径;IE8用随机生成的文件夹名兜底(需用户手动输入文件夹名,这里简化为随机字符串)。
  • 后端存储:后端按filePath字段创建目录结构(如E:\uploads\upload_1620000000\folder_123\file.txt),确保层级不变。

六、预算与合作模式(客户最关心的)

1. 预算控制(100元以内)

  • 源码一次性交付:提供完整前端Vue3组件、后端WebForm代码、数据库脚本,无后续授权费。
  • 免费技术支持:7*24小时远程协助(故障排查、版本升级、兼容性调试)。

2. 合作材料(满足客户采购要求)

  • 项目证明:提供过往外包项目合同(含项目名称、金额、验收报告)。
  • 技术资质:软件著作权证书(登记号:202XSRXXXXXX)、开发工具授权(Visual Studio 2022)。

兄弟,这套方案你拿给客户演示,保证验收时客户拍大腿说“这钱花得值”!有问题直接甩日志到群里(QQ群:374992201),老炮儿我24小时在线帮你改。记住:不会就查文档,卡壳就问群友——咱.NET程序员,接外包就是要“稳准狠”!

设置框架

安装.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/345355/

相关文章:

  • 2026年资深离婚律所推荐,北京元甲律所服务贴心 - myqiye
  • 教育行业如何实现大文件批量上传的方案总结?
  • 2026年热门的农业养殖项目/金头蜈蚣农业养殖项目项目优选指南 - 行业平台推荐
  • 总结户外亮化灯具制造厂,云南口碑好的品牌排名 - mypinpai
  • 2026年苏州靠谱婚房装修公司推荐,性价比高的品牌排行 - 工业推荐榜
  • 深圳昊客网络科技海外GEO优化推广科普:AI时代出海企业的流量密码 - 深圳昊客网络
  • 武汉新华电脑学校编程plc培训怎么样,费用怎么收 - 工业品牌热点
  • 2026年上海、浙江等地好用的纯化水设备批量定制品牌推荐 - 工业设备
  • 2026寒假放假通知SVG动画制作工具与指南 公众号文章必备组件合集 - peipei33
  • 雷达原理实验教学系统定制化开发哪里能做?核心厂家与能力解析 - 品牌推荐大师
  • VMWare下Windows XP的声音问题
  • 聊聊权威的AI自习室,精准数跃性价比高值得推荐 - 工业推荐榜
  • 2026年昆明知名的别墅全案设计品牌企业排名,哪家性价比高? - 工业设备
  • TP框架 之vue3简易论坛系统
  • java--线程安全问题
  • 好写作AI:专治“对着空白文档发呆”,你的灵感急救呼吸机!
  • 全网最全8个降AIGC网站,千笔AI助你高效降AI率
  • 真心不骗你!继续教育论文神器 —— 千笔ai写作
  • 导师推荐!千笔,顶尖配置的AI论文写作软件
  • 格式总出错?AI论文工具 千笔 VS 文途AI,本科生写作更轻松!
  • Jenkins节点拉取代码报错场景及解决方案全解析
  • chrome://settings/content/all
  • 2026年湿度仪靠谱生产商费用分析,昶艾科技定制生产价格合理 - 工业品网
  • 计算机网络经典问题透视:蜂窝网络切换如何“扼杀”你的TCP连接?
  • 计算机毕设java助学金管理系统 高校学生资助信息管理平台 校园奖助贷一体化服务系统
  • 英国供应链求职机构榜单:供应链机构深度测评 - 技研备忘录
  • 蠕动泵选哪个品牌?国内外优质品牌及选型指南 - 品牌推荐大师1
  • 2026年比较好的底部抽洗脸巾设备/洗脸巾设备厂家选购完整指南 - 行业平台推荐
  • 选购奢侈品回收服务,芯动中古名品性价比高的选择 - mypinpai
  • 探索六轴EtherCAT总线伺服涂布收卷机程序的奇妙世界