news 2026/4/23 13:42:02

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

作者头像

张小明

前端开发工程师

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/4/17 21:28:29

YOLO镜像支持Docker部署,一键启动服务

YOLO镜像支持Docker部署&#xff0c;一键启动服务 在智能工厂的产线旁&#xff0c;一台边缘服务器正同时处理来自十路摄像头的实时视频流——每秒上百帧的画面中&#xff0c;微小的划痕、缺失部件被精准识别并触发报警。运维人员只需一条命令就完成了整个视觉质检系统的上线&am…

作者头像 李华
网站建设 2026/4/19 9:08:55

YOLO镜像内置Label Studio,数据标注更便捷

YOLO镜像内置Label Studio&#xff0c;数据标注更便捷 在智能视觉项目开发中&#xff0c;一个常见的痛点是&#xff1a;拿到一批新图像后&#xff0c;团队往往要花上几天时间才能跑通第一个检测模型——不是因为算法太难&#xff0c;而是卡在了环境配置、工具切换和格式转换这些…

作者头像 李华
网站建设 2026/4/22 15:46:13

YOLO模型部署遇到问题?常见错误排查手册

YOLO模型部署常见问题与实战排查指南 在工业视觉系统日益智能化的今天&#xff0c;实时目标检测已经不再是实验室里的概念验证&#xff0c;而是产线上的刚性需求。无论是质检环节的缺陷识别、物流场景中的包裹分拣&#xff0c;还是智能安防中的行为分析&#xff0c;YOLO&#x…

作者头像 李华
网站建设 2026/4/23 10:53:46

springboot_ssm枣庄美食夜市一条街网站

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

作者头像 李华
网站建设 2026/4/23 10:51:31

YOLO训练技巧:如何设置最优学习率和Batch Size

YOLO训练技巧&#xff1a;如何设置最优学习率和Batch Size 在工业质检线上&#xff0c;一台搭载YOLO模型的视觉系统正高速运转&#xff0c;每秒处理上百帧图像以识别微小缺陷。然而工程师发现&#xff0c;模型在训练后期mAP停滞不前&#xff0c;验证损失波动剧烈——这背后很可…

作者头像 李华
网站建设 2026/4/23 8:18:42

YOLO目标检测性能评估指标详解(mAP, IoU, FPS)

YOLO目标检测性能评估指标详解&#xff08;mAP, IoU, FPS&#xff09; 在智能摄像头遍布街头巷尾、自动驾驶车辆悄然上路的今天&#xff0c;目标检测早已不再是实验室里的概念。从工厂流水线上的缺陷识别&#xff0c;到无人机航拍中的行人追踪&#xff0c;背后都离不开一个关键…

作者头像 李华