news 2026/5/30 13:38:17

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

作者头像

张小明

前端开发工程师

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/5/20 17:17:11

数字人直播实战:Live Avatar结合Gradio轻松实现交互

数字人直播实战:Live Avatar结合Gradio轻松实现交互 1. 为什么选择Live Avatar做数字人直播? 你可能已经试过不少数字人方案——有的需要专业动捕设备,有的依赖云端API按秒计费,有的生成视频要等半小时。而今天要聊的这个项目&a…

作者头像 李华
网站建设 2026/5/28 13:47:56

还在手动配环境?Z-Image-Turbo镜像一键解决烦恼

还在手动配环境?Z-Image-Turbo镜像一键解决烦恼 你是不是也经历过这样的深夜: 想试试最新的文生图模型,结果光是装CUDA、配PyTorch、下载30G权重就耗掉两小时; 好不容易跑通第一行代码,又卡在torch.compile不兼容、Mo…

作者头像 李华
网站建设 2026/5/28 11:26:46

Python 使用 subprocess 检测 Linux 用户是否存在,不存在则自动创建

一、背景说明 在 Linux 服务器自动化运维、初始化脚本或容器环境中,经常需要判断某个系统用户是否存在: 如果存在:直接使用如果不存在:自动创建用户 本文介绍如何使用 Python 的 subprocess 模块,调用系统命令 id 和…

作者头像 李华
网站建设 2026/5/24 8:44:26

GitHub 热榜项目 - 日榜(2026-01-25)

GitHub 热榜项目 - 日榜(2026-01-25) 生成于:2026-01-25 统计摘要 共发现热门项目: 10 个 榜单类型:日榜 本期热点趋势总结 本期GitHub趋势显示AI工程化应用全面爆发,核心围绕智能体开发与多模态创新。AI智能体成为热点&…

作者头像 李华
网站建设 2026/5/20 17:17:10

FSMN-VAD对比传统方法:AI模型更抗噪

FSMN-VAD对比传统方法:AI模型更抗噪 你有没有遇到过这样的尴尬? 会议录音里,空调嗡嗡声、键盘敲击声、偶尔的咳嗽声,全被语音识别系统当成了“有效语音”,结果转写出来一堆乱码; 车载语音助手在高速行驶时…

作者头像 李华
网站建设 2026/5/26 15:25:16

基于深度学习的行人车辆流量统计算法研究

目录深度学习在行人车辆流量统计中的应用关键技术方法典型应用场景性能优化方向挑战与解决方案源码文档获取/同行可拿货,招校园代理 :文章底部获取博主联系方式!深度学习在行人车辆流量统计中的应用 基于深度学习的行人车辆流量统计主要利用计算机视觉技…

作者头像 李华