news 2026/8/18 16:57:20

分享三种网页文件上传下载的解决方案及其实现思路?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
分享三种网页文件上传下载的解决方案及其实现思路?

📅 开发者日志:大文件上传系统的艰难实现之路

项目背景

2023年11月15日,周三,晴转多云

今天正式接手了一个具有挑战性的外包项目——构建一个支持20GB超大文件传输的Web系统。客户要求苛刻但预算有限,作为一名个人开发者,这既是一次机遇也是巨大的挑战。

需求分析

核心功能需求

  1. 超大文件支持:单文件20GB传输
  2. 批量传输:包含上千文件的文件夹层级结构保持
  3. 安全要求:SM4/AES加密传输与存储
  4. 稳定性:断点续传需持久化保存进度
  5. 兼容性:必须支持IE8等老旧浏览器

技术栈确认

  • 前端:Vue3 + WebUploader/原生H5
  • 后端:ASP.NET Core (.NET 8)
  • 数据库:SQL Server
  • 存储:阿里云OSS
  • 跨平台支持:Windows/macOS/Linux全平台

技术难点突破

文件夹结构保持方案

// 文件夹上传处理逻辑classFolderUploader{constructor(){this.folderStructure=newMap();// 使用Map保存完整路径}processEntry(entry,path=''){returnnewPromise((resolve)=>{if(entry.isFile){entry.file(file=>{constfullPath=`${path}/${file.name}`;this.folderStructure.set(fullPath,file);resolve();});}elseif(entry.isDirectory){constdirReader=entry.createReader();dirReader.readEntries(entries=>{constpromises=entries.map(subEntry=>this.processEntry(subEntry,`${path}/${entry.name}`));Promise.all(promises).then(resolve);});}});}}

断点续传持久化方案

// ASP.NET Core 断点续传状态管理publicclassUploadStateService{privatereadonlyConcurrentDictionary_stateCache;publicUploadStateService(){_stateCache=newConcurrentDictionary();}publicvoidSaveState(stringfileId,longchunkIndex){varstate=_stateCache.GetOrAdd(fileId,id=>newUploadState(id));state.UploadedChunks.Add(chunkIndex);// 持久化到数据库usingvardb=newAppDbContext();db.UploadStates.Update(state.ToEntity());db.SaveChanges();}publicUploadStateGetState(stringfileId){if(_stateCache.TryGetValue(fileId,outvarstate)){returnstate;}// 从数据库加载usingvardb=newAppDbContext();varentity=db.UploadStates.Find(fileId);returnentity?.ToModel()??newUploadState(fileId);}}

前后端完整交互示例

前端加密上传实现

// 基于WebUploader的加密上传组件exportclassSecureFileUploader{constructor(options){this.uploader=WebUploader.create({swf:'/libs/Uploader.swf',server:options.uploadUrl,chunked:true,chunkSize:4*1024*1024,// 4MB分片threads:3,prepareNextFile:true,fileSizeLimit:20*1024*1024*1024// 20GB});this.initEvents();this.cryptoWorker=newWorker('/js/crypto.worker.js');}initEvents(){this.uploader.on('uploadBeforeSend',(obj,data)=>{returnnewPromise(resolve=>{this.cryptoWorker.postMessage({type:'encrypt',data:obj.file,algorithm:'SM4'});this.cryptoWorker.onmessage=(e)=>{data.file=e.data;resolve(data);};});});this.uploader.on('fileQueued',file=>{conststate=localStorage.getItem(`upload_${file.id}`);if(state){this.uploader.uploader.upload(file,JSON.parse(state));}});}}

后端分片处理实现

// ASP.NET Core 文件分片控制器[ApiController][Route("api/upload")]publicclassUploadController:ControllerBase{privatereadonlyUploadStateService_stateService;privatereadonlyIOSSClient_ossClient;publicUploadController(UploadStateServicestateService,IOSSClientossClient){_stateService=stateService;_ossClient=ossClient;}[HttpPost("chunk")]publicasyncTaskUploadChunk([FromForm]IFormFilefile,[FromForm]stringfileId,[FromForm]intchunkIndex,[FromForm]inttotalChunks){usingvarmemoryStream=newMemoryStream();awaitfile.CopyToAsync(memoryStream);// 解密处理vardecryptedData=CryptoHelper.SM4Decrypt(memoryStream.ToArray(),Configuration["EncryptionKey"]);// 存储到OSSvarchunkKey=$"{fileId}/{chunkIndex}";await_ossClient.PutObjectAsync("uploads",chunkKey,newMemoryStream(decryptedData));// 更新状态_stateService.SaveState(fileId,chunkIndex);if(chunkIndex==totalChunks-1){// 触发文件合并BackgroundJob.Enqueue(()=>MergeFileChunks(fileId));}returnOk(new{success=true});}[NonAction]publicasyncTaskMergeFileChunks(stringfileId){varstate=_stateService.GetState(fileId);varfinalKey=$"files/{DateTime.Now:yyyyMMdd}/{fileId}";usingvarfinalStream=newMemoryStream();foreach(varchunkinstate.UploadedChunks.OrderBy(x=>x)){varchunkKey=$"{fileId}/{chunk}";varchunkData=await_ossClient.GetObjectAsync("uploads",chunkKey);awaitchunkData.CopyToAsync(finalStream);await_ossClient.DeleteObjectAsync("uploads",chunkKey);}finalStream.Position=0;await_ossClient.PutObjectAsync("final",finalKey,finalStream);}}

兼容性处理方案

IE8兼容层实现

// ie8-wrapper.js(function(){// Polyfill for File APIif(!window.File){window.File=function(){};window.FileReader=function(){this.readAsArrayBuffer=function(blob){// IE8的ActiveX实现varaxo=newActiveXObject("ADODB.Stream");axo.Type=1;// 二进制类型axo.Open();axo.LoadFromFile(blob.name);varbuffer=axo.Read();this.onload({target:{result:buffer}});};};}// Polyfill for FormDataif(!window.FormData){window.FormData=function(){this.append=function(key,value){// 使用隐藏iframe实现表单提交variframe=document.createElement('iframe');iframe.name='formdata-iframe';document.body.appendChild(iframe);varform=document.createElement('form');form.target=iframe.name;form.method='POST';form.enctype='multipart/form-data';varinput=document.createElement('input');input.type='hidden';input.name=key;input.value=value;form.appendChild(input);document.body.appendChild(form);form.submit();};};}})();

开发文档结构

📂 项目文档 ├── 1. 系统架构设计 │ ├── 1.1 技术栈说明 │ ├── 1.2 系统架构图 │ └── 1.3 部署拓扑图 ├── 2. API接口文档 │ ├── 2.1 上传接口规范 │ ├── 2.2 下载接口规范 │ └── 2.3 状态管理接口 ├── 3. 前端集成指南 │ ├── 3.1 WebUploader配置 │ ├── 3.2 加密模块使用 │ └── 3.3 兼容性处理 ├── 4. 后端部署手册 │ ├── 4.1 环境配置 │ ├── 4.2 数据库初始化 │ └── 4.3 性能调优 └── 5. 运维监控 ├── 5.1 日志收集 ├── 5.2 异常告警 └── 5.3 扩容方案

项目总结

已解决问题

  1. 通过分片加密上传实现了20GB文件支持
  2. 使用目录树遍历算法保持文件夹结构
  3. 结合本地存储和数据库实现持久化断点续传
  4. 开发多套降级方案保证IE8兼容性

待解决问题

  1. 极端网络环境下分片成功率优化
  2. OSS批量操作的性能瓶颈
  3. 国产浏览器(红莲花等)的特殊适配

后记:这个项目让我深刻体会到企业级文件传输的复杂性。欢迎同行加入QQ群374992201交流大文件传输技术,共同应对外包项目中的各种挑战。

设置框架

安装.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/8/16 19:53:56

通义千问3-14B性能极限?A100上120 token/s部署实测

通义千问3-14B性能极限?A100上120 token/s部署实测 1. 为什么Qwen3-14B值得你停下来看这一眼 你有没有遇到过这样的困境:想用一个真正好用的大模型,但服务器只有一张A100;想处理几十万字的合同或论文,又怕长文本推理…

作者头像 李华
网站建设 2026/8/15 5:49:23

工业触摸屏:Elo、AMT 和 Microchip

工业触摸屏:Elo、AMT 和 Microchip Elo、AMT 和 Microchip 是工业电阻式触控控制器的三大代表:Elo 以 AccuTouch 五线电阻技术著称,强调高可靠性和全球认证;AMT 的 PenMount 系列控制器专注工业级应用,具备宽温度范围…

作者头像 李华
网站建设 2026/8/18 13:34:22

零基础入门Glyph视觉推理,一键启动长文本理解新方式

零基础入门Glyph视觉推理,一键启动长文本理解新方式 1. 这不是“又一个OCR”,而是一种全新的长文本处理思路 你有没有遇到过这样的场景:手头有一份50页的PDF技术白皮书、一份200页的合同扫描件,或者一篇长达3万字的行业分析报告…

作者头像 李华
网站建设 2026/8/18 10:33:45

【风电功率预测】别再只卷模型了:提准最快的捷径,是把“输入稳定性”做成硬指标

风电功率预测这两年为什么越来越“卷”? 不是因为大家突然更爱研究算法,而是市场把“预测误差”变成了真金白银的成本项。现货与中长期组合交易更常态化,偏差考核、结算波动变得更敏感调度对“可执行的提前量”要求更高:不仅要准&…

作者头像 李华
网站建设 2026/8/17 12:23:02

Tampermonkey篡改猴200+插件打包下载

当Chrome商店无法访问时,知乎网友们摸索出了一套成熟的Tampermonkey离线安装方案。2026年初的最新教程显示,通过CRX文件本地部署GreasyFork脚本库组合,即使在无网络环境下也能搭建完整的脚本生态。 开始进入正题 油猴脚本不运行了&#xff…

作者头像 李华
网站建设 2026/8/16 6:23:51

为什么Qwen3-14B能省事?128k长文单卡推理部署解析

为什么Qwen3-14B能省事?128k长文单卡推理部署解析 1. 它不是“小模型”,而是“刚刚好”的大模型守门员 很多人看到“14B”就下意识划走——觉得参数不够大、性能不够强、跑不起来新任务。但Qwen3-14B恰恰打破了这个惯性认知:它不是在参数规…

作者头像 李华