news 2026/4/17 21:22:06

多平台大文件上传控件的原理与实现思路分享

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
多平台大文件上传控件的原理与实现思路分享

【一个大三生的“渡劫”级毕业设计实录】

(拍桌)家人们谁懂啊!导师让我用ASP.NET WebForm搞个支持10G文件上传的系统,还要兼容IE8和龙芯浏览器这种“上古神器”!更离谱的是必须用原生JS实现(Vue3?那是我毕业后再学的技能啊!)


前端篇:与IE8和国产浏览器的“三角恋”

// 兼容IE8+国产浏览器的uploader.js(头发已掉光版)functionNationalCompatibleUploader(){this.chunkSize=5*1024*1024;// 5MB分片(IE8友好)this.progressKeyPrefix="upload_progress_";// 浏览器检测(专治各种不服)this.detectBrowser=function(){constua=navigator.userAgent.toLowerCase();if(ua.indexOf("msie")>-1)return"IE"+ua.match(/msie (\d+)/)[1];if(ua.indexOf("longxin")>-1)return"Longxin";// 龙芯浏览器if(ua.indexOf("redlotus")>-1)return"RedLotus";// 红莲花return"Modern";};// 跨浏览器存储方案(IE8用userData,现代用localStorage)this.saveProgress=function(fileMd5,chunkIndex,totalChunks){constprogress={chunkIndex,totalChunks};constkey=this.progressKeyPrefix+fileMd5;if(this.detectBrowser()==="IE8"){// IE8的降级方案(实际项目请用flash或cookie)document.cookie=key+"="+encodeURIComponent(JSON.stringify(progress))+"; expires=Fri, 31 Dec 9999 23:59:59 GMT";}else{try{localStorage.setItem(key,JSON.stringify(progress));}catch(e){// 国产浏览器可能限制localStorage大小this.fallbackToCookie(key,progress);}}};// 分片上传(兼容所有浏览器)this.uploadChunk=function(file,chunkIndex,totalChunks){constblob=file.slice(chunkIndex*this.chunkSize,(chunkIndex+1)*this.chunkSize);constformData=newFormData();formData.append("file",blob);formData.append("chunkIndex",chunkIndex);formData.append("totalChunks",totalChunks);formData.append("fileName",file.name);formData.append("md5",this.calculatePseudoMd5(file));// IE8无MD5constxhr=newXMLHttpRequest();xhr.open("POST","/UploadHandler.ashx",true);// WebForm专用xhr.onreadystatechange=function(){if(xhr.readyState===4&&xhr.status===200){constresponse=JSON.parse(xhr.responseText);if(response.success){this.saveProgress(response.fileId,chunkIndex,totalChunks);}}}.bind(this);xhr.send(formData);};// IE8无MD5的降级方案this.calculatePseudoMd5=function(file){if(this.detectBrowser()!=="IE8"){// 现代浏览器用crypto API(实际项目请用真正的MD5)return"modern_"+Math.random().toString(36).substr(2);}return"ie8_"+file.name+"_"+file.size;};}

后端篇:ASP.NET WebForm的“复古”实现

// UploadHandler.ashx - WebForm专用上传处理器<%@WebHandlerLanguage="C#"Class="UploadHandler"%>usingSystem;usingSystem.IO;usingSystem.Web;usingSystem.Security.Cryptography;// 用于加密(示例用简单加密)publicclassUploadHandler:IHttpHandler{// 配置信息(实际项目请用web.config)privatestaticreadonlystringTempDir=Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"TempUploads");privatestaticreadonlystringOssEndpoint="your-oss-endpoint";privatestaticreadonlystringAccessKey="your-access-key";publicvoidProcessRequest(HttpContextcontext){context.Response.ContentType="application/json";try{// 获取上传参数intchunkIndex=int.Parse(context.Request["chunkIndex"]);inttotalChunks=int.Parse(context.Request["totalChunks"]);stringfileName=context.Request["fileName"];stringfileId=context.Request["md5"];// 实际是伪MD5// 创建临时目录stringchunkDir=Path.Combine(TempDir,fileId);if(!Directory.Exists(chunkDir)){Directory.CreateDirectory(chunkDir);}// 保存分片stringchunkPath=Path.Combine(chunkDir,$"chunk_{chunkIndex}");context.Request.Files[0].SaveAs(chunkPath);// 如果是最后一个分片,合并文件if(chunkIndex==totalChunks-1){stringfinalPath=Path.Combine(chunkDir,fileName);MergeChunks(chunkDir,finalPath,totalChunks);// 加密存储(示例用简单异或加密)stringencryptedPath=EncryptFilePath(finalPath);// 上传到OSS(伪代码)UploadToOss(finalPath,encryptedPath);// 清理临时文件Directory.Delete(chunkDir,true);context.Response.Write("{\"success\":true,\"fileId\":\""+fileId+"\"}");}else{context.Response.Write("{\"success\":true}");}}catch(Exceptionex){context.Response.Write("{\"success\":false,\"error\":\""+ex.Message+"\"}");}}// 合并分片(IE8兼容的合并方式)privatevoidMergeChunks(stringchunkDir,stringfinalPath,inttotalChunks){using(FileStreamfs=newFileStream(finalPath,FileMode.Create)){for(inti=0;i<totalChunks;i++){byte[]chunkData=File.ReadAllBytes(Path.Combine(chunkDir,$"chunk_{i}"));fs.Write(chunkData,0,chunkData.Length);}}}// 简单加密(实际项目请用AES)privatestringEncryptFilePath(stringpath){byte[]data=System.Text.Encoding.UTF8.GetBytes(path);for(inti=0;i<data.Length;i++){data[i]=(byte)(data[i]^0x55);// 简单异或}returnConvert.ToBase64String(data);}publicboolIsReusable{get{returnfalse;}}}

文件夹上传的“黑科技”实现

// 文件夹上传核心逻辑(兼容所有浏览器)functionuploadFolder(folderInput){constfiles=[];constfolderStack=[...folderInput.files];// 用栈实现DFS遍历// 构建文件层级结构(伪代码)functionbuildFileTree(fileEntries){consttree={name:"root",type:"dir",children:[]};// 实际项目需要用递归遍历FileEntry(IE8不支持)// 这里用简化版模拟fileEntries.forEach(file=>{constpathParts=file.webkitRelativePath.split('/');// Chrome专用// IE8/国产浏览器降级方案:用文件名+随机前缀模拟路径letcurrentLevel=tree;pathParts.forEach((part,index)=>{constisLast=index===pathParts.length-1;constexistingNode=currentLevel.children.find(n=>n.name===part);if(isLast){// 是文件currentLevel.children.push({name:part,type:"file",size:file.size,path:file.webkitRelativePath// 实际路径});}elseif(!existingNode){// 是目录constnewDir={name:part,type:"dir",children:[]};currentLevel.children.push(newDir);currentLevel=newDir;}else{currentLevel=existingNode;}});});returntree;}// 实际项目需要处理:// 1. IE8的文件夹上传(需要用ActiveXObject)// 2. 国产浏览器的特殊API// 3. 进度保存与恢复}

血泪经验总结:

  1. IE8兼容性

    • ActiveXObject读取文件夹(需要降低安全设置)
    • 降级方案:让用户先压缩成ZIP再上传
    • 存储用userData替代localStorage
  2. 国产浏览器适配

    • 龙芯浏览器:基于Chromium但API有差异
    • 红莲花浏览器:类似IE11但更严格
    • 测试方案:用BrowserStack或本地虚拟机
  3. 加密实现

    • 传输加密:用HTTPS(强制)
    • 存储加密:
      • 前端:CryptoJS(现代浏览器)
      • 后端:AES(C#用System.Security.Cryptography
      • IE8:用简单异或加密(不推荐生产环境)
  4. 文件夹上传

    • 现代浏览器:用webkitRelativePath
    • IE8:用``的降级方案
    • 存储结构示例:
    {"name":"项目资料","type":"dir","children":[{"name":"文档","type":"dir","children":[{"name":"需求.docx","type":"file","size":102400}]}]}

求职彩蛋:

正在疯狂投递简历中,求各位大佬内推!擅长:

  • 写兼容IE8的代码(头发还在)
  • 和产品经理“友好交流”(物理)
  • 调试ASP.NET WebForm的“神秘”错误

QQ群:374992201(进群抢红包,推荐项目拿提成,说不定还能找到工作!)

(PS:导师说这个系统要是能跑起来,直接给优秀毕业设计!兄弟们靠你们了!群里有大佬帮我调试过代码,真的能跑通!)

设置框架

安装.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/3/31 2:40:14

YOLO镜像内置Prometheus监控组件,运维更轻松

YOLO镜像内置Prometheus监控组件&#xff0c;运维更轻松 在智能制造工厂的视觉检测线上&#xff0c;一台边缘设备正以每秒百帧的速度运行着YOLO模型进行缺陷识别。突然&#xff0c;推理延迟从50ms飙升至300ms&#xff0c;但系统并未报警——因为没人知道该看什么、怎么看。这种…

作者头像 李华
网站建设 2026/4/16 13:06:11

Thinkphp_Laravel框架开发的vue家庭个人理财收支管理系统_5x6nf

目录具体实现截图项目开发技术介绍PHP核心代码部分展示系统结论源码获取/同行可拿货,招校园代理具体实现截图 本系统&#xff08;程序源码数据库调试部署讲解&#xff09;带文档1万字以上 同行可拿货,招校园代理 Thinkphp_Laravel框架开发的vue家庭个人理财收支管理系统_5x6n…

作者头像 李华
网站建设 2026/4/10 16:42:47

springboot_ssm整体衣柜材料定制系统

目录 具体实现截图系统所用技术介绍写作提纲核心代码部分展示系统性能结论源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01; 具体实现截图 springboot_ssm整体衣柜材料定制系统 系统所用技术介绍 本系统采取了一系列的设计原则&…

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

springboot_ssm智能高端家具家居行业门户网站

目录具体实现截图系统所用技术介绍写作提纲核心代码部分展示系统性能结论源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;具体实现截图 springboot_ssm智能高端家具家居行业门户网站 系统所用技术介绍 本系统采取了一系列的设计原…

作者头像 李华
网站建设 2026/4/16 16:44:50

springboot_ssm牙科诊所项目预约管理系统

目录具体实现截图系统所用技术介绍写作提纲核心代码部分展示系统性能结论源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;具体实现截图 springboot_ssm牙科诊所项目预约管理系统 系统所用技术介绍 本系统采取了一系列的设计原则&…

作者头像 李华
网站建设 2026/4/16 22:25:29

基于SpringBoot的学生在线学习系统的设计与实现(源码+lw+部署文档+讲解等)

背景及意义 在教育数字化转型加速、学生自主学习需求增长的背景下&#xff0c;传统学习模式存在 “资源分散、互动不足、进度难追踪” 的痛点。基于 SpringBoot 构建的学生在线学习系统&#xff0c;适配管理员、教师、学生等角色&#xff0c;实现课程管理、在线学习、互动交流、…

作者头像 李华