HTML如何实现网页大文件上传的拖拽功能?
2026/5/24 14:25:45 网站建设 项目流程

开发日记:大文件上传系统攻坚记
日期:2023年XX月XX日
天气:晴(但心情像在调试IE8的阴天)


一、需求拆解:从"不可能"到"可能"

客户的需求像一座高山:

  • 20G文件传输(阿里云OSS单文件上限5TB,但浏览器内存是瓶颈)
  • IE8兼容(默默掏出XDomainRequestActiveXObject的祖传代码)
  • 文件夹层级保留(需递归处理``的FileSystemEntryAPI)
  • 断点续传+加密(分片上传+本地存储恢复点+Web Crypto API)

技术选型

  • 放弃WebUploader(IE8支持不足),选择原生JS+H5 File API
  • 加密方案:SM4/AES通过forge.js兼容旧浏览器
  • 断点续传:localStorage+服务端分片记录

二、前端核心代码:文件夹上传与断点续传

1. 文件夹上传(递归扫描)
// 获取文件夹所有文件(兼容IE10+,IE8需ActiveX降级方案)asyncfunctionscanDirectory(directory){constfiles=[];conststack=[directory];while(stack.length){constentry=stack.pop();if(entry.isFile){files.push(awaitgetFile(entry));}elseif(entry.isDirectory){constreader=entry.createReader();constentries=awaitnewPromise(resolve=>reader.readEntries(resolve));stack.push(...entries);}}returnfiles;}// IE8降级方案(需用户手动选择多个文件)functionhandleIE8Fallback(){constinput=document.createElement('input');input.type='file';input.multiple=true;input.onchange=()=>uploadFiles(input.files);input.click();}
2. 分片上传+断点续传
classChunkUploader{constructor(file,options){this.file=file;this.chunkSize=5*1024*1024;// 5MB/chunkthis.totalChunks=Math.ceil(file.size/this.chunkSize);this.uploadedChunks=JSON.parse(localStorage.getItem(file.name)||'[]');}asyncupload(){for(leti=0;i<this.totalChunks;i++){if(this.uploadedChunks.includes(i))continue;constchunk=this.file.slice(i*this.chunkSize,(i+1)*this.chunkSize);awaitthis.sendChunk(chunk,i);this.uploadedChunks.push(i);localStorage.setItem(this.file.name,JSON.stringify(this.uploadedChunks));}}asyncsendChunk(chunk,index){constformData=newFormData();formData.append('chunk',chunk);formData.append('chunkIndex',index);formData.append('totalChunks',this.totalChunks);formData.append('fileId',btoa(this.file.name+this.file.size));// 唯一标识returnfetch('/api/upload',{method:'POST',body:formData});}}

三、后端C#代码:分片处理与加密存储

1. 分片接收(ASP.NET WebForm)
[WebMethod]publicstaticstringUploadChunk(){HttpPostedFilechunk=HttpContext.Current.Request.Files["chunk"];intindex=int.Parse(HttpContext.Current.Request["chunkIndex"]);stringfileId=HttpContext.Current.Request["fileId"];// 存储分片到临时目录stringtempPath=Path.Combine(Server.MapPath("~/App_Data/Temp"),fileId);Directory.CreateDirectory(tempPath);chunk.SaveAs(Path.Combine(tempPath,index.ToString()));// 检查是否完成if(AllChunksReceived(tempPath,int.Parse(HttpContext.Current.Request["totalChunks"]))){MergeFile(tempPath,fileId);}return"OK";}
2. SM4加密存储(使用BouncyCastle库)
publicstaticvoidEncryptToOSS(Streaminput,stringossKey){varengine=newSM4Engine();varkey=Encoding.UTF8.GetBytes("16-byte-secret-key");engine.Init(true,newKeyParameter(key));using(varossClient=newOssClient(endpoint,accessKeyId,accessKeySecret))using(varcryptoStream=newCryptoStream(input,engine,CryptoStreamMode.Read)){ossClient.PutObject(bucketName,ossKey,cryptoStream);}}

四、踩坑实录

  1. IE8的棺材板快压不住了
    • 解决方案:对文件夹上传降级为多文件选择,用swfUpload后备方案
  2. 20G文件内存溢出
    • 优化:采用FileReaderreadAsArrayBuffer分段处理
  3. 文件夹层级丢失
    • 关键:上传时携带相对路径,如/科研资料/2023/实验报告.pdf

五、部署与协作

  • 阿里云OSS配置:开启断点续传和跨域规则
  • SQL Server设计
    CREATETABLEFileTransfers(FileIdVARCHAR(255)PRIMARYKEY,OriginalName NVARCHAR(255),OSSPathVARCHAR(255),ChunkCountINT,CompletedChunksVARCHAR(MAX)-- JSON格式存储已上传分片)
  • 接单群协作:代码已上传至群文件(QQ群:374992201),含完整文档

明日计划

  • 测试CentOS下Mono运行ASP.NET的兼容性
  • 编写IE8的ActiveX加密模块(仿佛回到2010年)

签名
—— 一个在古董浏览器和现代需求间挣扎的开发者

设置框架

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

创建数据库

配置数据库连接信息

检查数据库配置

访问页面进行测试


相关参考:
文件保存位置,

效果预览

文件上传

文件刷新续传

支持离线保存文件进度,在关闭浏览器,刷新浏览器后进行不丢失,仍然能够继续上传

文件夹上传

支持上传文件夹并保留层级结构,同样支持进度信息离线保存,刷新页面,关闭页面,重启系统不丢失上传进度。

批量下载

支持文件批量下载

下载续传

文件下载支持离线保存进度信息,刷新页面,关闭页面,重启系统均不会丢失进度信息。

文件夹下载

支持下载文件夹,并保留层级结构,不打包,不占用服务器资源。

下载示例

下载完整示例

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询