news 2026/4/17 5:48:18

前端如何通过JavaScript实现.NET Core大文件分片上传的进度回传?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
前端如何通过JavaScript实现.NET Core大文件分片上传的进度回传?

大文件传输解决方案设计

作为上海超时代软件有限公司的项目负责人,我将针对贵司的大文件传输需求提出一套完整的解决方案。

需求分析与挑战

根据贵司的需求,我总结出以下关键点和技术挑战:

  1. 超大文件传输:单文件100G左右,远超常规Web应用处理范围
  2. 文件夹传输:需保留层级结构,且非打包方式下载
  3. 高可靠性断点续传:需支持浏览器刷新/关闭后继续
  4. 加密要求:支持SM4和AES,传输和存储均需加密
  5. 广泛兼容性:从IE8到现代浏览器,多种操作系统
  6. 高并发处理:避免服务器资源耗尽

技术方案设计

架构概述

我们建议采用分层架构设计:

客户端层(Web/PC端) → API网关层 → 业务逻辑层 → 文件存储层

前端设计方案

核心组件
// 基于Vue2的文件上传组件示例Vue.component('super-file-upload',{props:{chunkSize:{type:Number,default:5*1024*1024},// 5MB分片maxRetries:{type:Number,default:3},allowFolders:{type:Boolean,default:true}},data(){return{files:[],folders:[],progress:{},status:'idle'}},methods:{asynchandleFileChange(e){constitems=e.dataTransfer?e.dataTransfer.items:e.target.files;awaitthis.processItems(items);},asyncprocessItems(items){for(leti=0;i<items.length;i++){constitem=items[i];if(item.kind==='file'){if(item.webkitGetAsEntry){constentry=item.webkitGetAsEntry();if(entry.isDirectory){awaitthis.processDirectory(entry);}else{this.files.push(entry.file());}}else{this.files.push(item.getAsFile());}}}},asyncuploadFiles(){for(constfileofthis.files){awaitthis.uploadFile(file);}for(constfolderofthis.folders){awaitthis.uploadFolder(folder);}},asyncuploadFile(file){constfileId=this.generateFileId(file);constchunkCount=Math.ceil(file.size/this.chunkSize);// 检查已上传分片constuploadedChunks=awaitthis.checkUploadedChunks(fileId);for(letchunkIndex=0;chunkIndex<chunkCount;chunkIndex++){if(uploadedChunks.includes(chunkIndex))continue;constchunk=file.slice(chunkIndex*this.chunkSize,Math.min((chunkIndex+1)*this.chunkSize,file.size));awaitthis.uploadChunk(fileId,chunkIndex,chunkCount,chunk);}awaitthis.completeUpload(fileId,file.name,file.size);}}});
IE8兼容方案
// IE8特殊处理if(navigator.userAgent.indexOf('MSIE 8')>-1){document.attachEvent('ondrop',function(e){e=window.event;e.returnValue=false;// IE8文件夹处理逻辑varfiles=[];for(vari=0;i<e.dataTransfer.files.length;i++){files.push(e.dataTransfer.files[i]);}// 简化处理,IE8不支持文件夹上传vm.handleFiles(files);});}

后端设计方案

核心接口
// ASP.NET WebForm 断点续传处理publicclassFileUploadHandler:IHttpHandler{publicvoidProcessRequest(HttpContextcontext){stringaction=context.Request["action"];switch(action){case"init":HandleInitUpload(context);break;case"upload":HandleChunkUpload(context);break;case"complete":HandleCompleteUpload(context);break;case"resume":HandleResumeUpload(context);break;}}privatevoidHandleInitUpload(HttpContextcontext){stringfileId=Guid.NewGuid().ToString();stringfileName=context.Request["name"];longfileSize=long.Parse(context.Request["size"]);intchunkSize=int.Parse(context.Request["chunkSize"]);// 初始化上传记录varuploadRecord=newUploadRecord{FileId=fileId,FileName=fileName,FileSize=fileSize,ChunkSize=chunkSize,Status=UploadStatus.InProgress,CreateTime=DateTime.Now};// 存储到数据库using(vardb=newUploadDbContext()){db.UploadRecords.Add(uploadRecord);db.SaveChanges();}// 返回响应context.Response.ContentType="application/json";context.Response.Write(JsonConvert.SerializeObject(new{success=true,fileId=fileId}));}privatevoidHandleChunkUpload(HttpContextcontext){stringfileId=context.Request["fileId"];intchunkIndex=int.Parse(context.Request["chunkIndex"]);intchunkCount=int.Parse(context.Request["chunkCount"]);// 获取上传记录UploadRecordrecord;using(vardb=newUploadDbContext()){record=db.UploadRecords.FirstOrDefault(r=>r.FileId==fileId);}// 处理分片varchunkData=context.Request.Files[0].InputStream;stringtempPath=GetTempFilePath(fileId,chunkIndex);// 加密分片using(varfileStream=newFileStream(tempPath,FileMode.Create))using(varcryptoStream=CreateEncryptionStream(fileStream)){chunkData.CopyTo(cryptoStream);}// 更新上传进度using(vardb=newUploadDbContext()){varchunkRecord=newUploadChunk{FileId=fileId,ChunkIndex=chunkIndex,Status=ChunkStatus.Completed,UpdateTime=DateTime.Now};db.UploadChunks.Add(chunkRecord);db.SaveChanges();}context.Response.Write(JsonConvert.SerializeObject(new{success=true}));}// 其他处理方法...}
加密模块
publicstaticclassFileEncryptor{publicstaticStreamCreateEncryptionStream(StreamoutputStream){stringalgorithm=ConfigurationManager.AppSettings["EncryptionAlgorithm"]??"SM4";if(algorithm=="SM4"){// 国密SM4加密varkey=GetEncryptionKey();variv=GenerateIV();varsm4=newSM4Engine();returnnewCryptoStream(outputStream,sm4.CreateEncryptor(key,iv),CryptoStreamMode.Write);}else{// AES加密varaes=Aes.Create();aes.Key=GetEncryptionKey();aes.IV=GenerateIV();returnnewCryptoStream(outputStream,aes.CreateEncryptor(),CryptoStreamMode.Write);}}// 其他加密相关方法...}

数据库设计

-- 上传记录表CREATETABLEUploadRecords(IdINTPRIMARYKEYIDENTITY,FileId UNIQUEIDENTIFIERNOTNULL,FileName NVARCHAR(255)NOTNULL,FileSizeBIGINTNOTNULL,ChunkSizeINTNOTNULL,StatusTINYINTNOTNULL,-- 0:进行中,1:已完成,2:已取消CreateTimeDATETIMENOTNULL,CompleteTimeDATETIMENULL,UserIdINTNULL,ProjectIdINTNULL);-- 上传分片表CREATETABLEUploadChunks(IdINTPRIMARYKEYIDENTITY,FileId UNIQUEIDENTIFIERNOTNULL,ChunkIndexINTNOTNULL,StatusTINYINTNOTNULL,-- 0:未开始,1:进行中,2:已完成,3:失败StartTimeDATETIMENULL,EndTimeDATETIMENULL,RetryCountINTDEFAULT0,ErrorMessage NVARCHAR(MAX)NULL);-- 文件存储表CREATETABLEFileStorage(IdINTPRIMARYKEYIDENTITY,FileId UNIQUEIDENTIFIERNOTNULL,FileName NVARCHAR(255)NOTNULL,FilePath NVARCHAR(MAX)NOTNULL,FileSizeBIGINTNOTNULL,IsDirectoryBITNOTNULL,ParentId UNIQUEIDENTIFIERNULL,EncryptionTypeTINYINTNOTNULL,-- 0:无,1:AES,2:SM4EncryptionKey NVARCHAR(MAX)NULL,CreateTimeDATETIMENOTNULL,CreateUserIdINTNULL);

核心功能实现细节

断点续传持久化方案

  1. 服务端存储:所有上传状态保存在数据库中,不依赖会话
  2. 客户端存储:使用localStorage+IndexedDB存储上传进度
  3. 恢复机制
    • 上传前检查服务端已接收的分片
    • 重新计算文件指纹(MD5)确保文件未更改
    • 从最后失败的分片继续上传

文件夹处理方案

  1. 客户端

    • 使用HTML5 Directory API获取文件夹结构
    • 递归处理所有子文件和子文件夹
    • 维护相对路径关系
  2. 服务端

    • 按照客户端发送的路径信息重建目录结构
    • 每个文件单独处理,但关联相同的父目录ID
    • 支持批量操作提高性能

高并发下载优化

  1. 零打包下载

    • 采用文件清单+逐个下载的方式
    • 客户端根据清单自行重建文件夹结构
    • 服务端仅提供单个文件下载流
  2. 限流保护

    // 下载限流中间件publicclassDownloadThrottleMiddleware{privatereadonlyRequestDelegate_next;privatestaticreadonlyConcurrentDictionary_rateLimits=newConcurrentDictionary();publicDownloadThrottleMiddleware(RequestDelegatenext){_next=next;}publicasyncTaskInvoke(HttpContextcontext){if(!context.Request.Path.StartsWithSegments("/download")){await_next(context);return;}varclientIp=context.Connection.RemoteIpAddress.ToString();varsemaphore=_rateLimits.GetOrAdd(clientIp,_=>newSemaphoreSlim(3));if(!awaitsemaphore.WaitAsync(TimeSpan.FromSeconds(10))){context.Response.StatusCode=429;awaitcontext.Response.WriteAsync("Too many requests");return;}try{await_next(context);}finally{semaphore.Release();}}}

部署与集成方案

私有云部署

  1. 独立服务:将文件传输功能部署为独立服务

  2. 微服务架构

    • 上传/下载服务
    • 加密服务
    • 存储管理服务
  3. 负载均衡

    • 使用Nginx进行负载均衡
    • 支持水平扩展

阿里云OSS集成

publicclassOssFileStorage:IFileStorage{privatereadonlyOssClient_client;privatereadonlystring_bucketName;publicOssFileStorage(stringendpoint,stringaccessKey,stringsecretKey,stringbucketName){_client=newOssClient(endpoint,accessKey,secretKey);_bucketName=bucketName;}publicasyncTaskUploadFileAsync(stringobjectName,Streamstream,IDictionarymetadata=null){varrequest=newPutObjectRequest(_bucketName,objectName,stream);if(metadata!=null){request.Metadata=metadata;}awaitTask.Run(()=>_client.PutObject(request));}// 其他方法实现...}

性能优化措施

  1. 分片策略

    • 动态分片大小(5MB-20MB可调)
    • 根据网络状况自动调整
  2. 并行上传

    // 前端并行上传控制constMAX_PARALLEL=3;constactiveUploads=[];asyncfunctionuploadWithParallelControl(file){while(activeUploads.length>=MAX_PARALLEL){awaitPromise.race(activeUploads);}constuploadPromise=uploadFile(file);activeUploads.push(uploadPromise);try{awaituploadPromise;}finally{constindex=activeUploads.indexOf(uploadPromise);if(index!==-1){activeUploads.splice(index,1);}}}
  3. 内存优化

    • 流式处理避免大内存占用
    • 分片磁盘缓存替代内存缓存

测试建议

  1. 兼容性测试矩阵

    浏览器/系统Windows 7Windows 10macOSLinux
    IE8---
    Chrome
    Firefox
    360安全--
  2. 性能测试场景

    • 单文件100GB传输
    • 10万小文件(总计100GB)文件夹传输
    • 50并发用户同时上传/下载

授权与合作方案

基于贵司需求,我们建议采用以下合作模式:

  1. 年度授权:18万元/年,不限项目数量

    • 包含所有功能模块
    • 不限部署实例数
    • 产品升级和技术支持
  2. 交付物

    • 全套源代码和文档
    • 软件著作权证书
    • 央企合作案例证明(5个以上)
    • 信创环境适配认证
    • 专业技术培训
  3. 实施计划

    • 第1周:环境准备与需求确认
    • 第2-3周:核心功能开发
    • 第4周:集成测试
    • 第5周:上线部署

技术支持与保障

  1. 服务承诺

    • 7×12小时技术支持
    • 紧急问题2小时内响应
    • 定期版本更新
  2. 扩展性保障

    • 支持后续功能扩展
    • 支持集群化部署
    • 支持自定义加密模块

如需进一步讨论技术细节或查看完整演示,欢迎随时联系。

设置框架

安装.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/11 4:46:35

Excalidraw与Thanos监控长期存储架构图

Excalidraw 与 Thanos&#xff1a;用视觉语言解构云原生监控架构 在一次深夜的线上故障复盘会上&#xff0c;团队盯着屏幕里那张密密麻麻的监控架构图——标准矩形框、规整连线、层层嵌套的组件&#xff0c;没人能一口气讲清楚数据到底从哪来、往哪去。突然有人提议&#xff1…

作者头像 李华
网站建设 2026/4/17 8:36:55

Excalidraw手绘白板神器:AI赋能下的技术架构图一键生成

Excalidraw&#xff1a;当手绘白板遇上AI&#xff0c;技术图一键生成的实践之路 在一次远程架构评审会议中&#xff0c;团队正为如何快速呈现微服务调用链而发愁。有人提议&#xff1a;“要不我们画个图&#xff1f;”——话音刚落&#xff0c;另一人苦笑&#xff1a;“又要开V…

作者头像 李华
网站建设 2026/4/17 20:30:45

Excalidraw图形成本估算标注

Excalidraw&#xff1a;当手绘白板遇上AI&#xff0c;如何重塑图形化成本估算 在一次远程产品评审会上&#xff0c;团队正为新功能的技术实现路径争论不休。产品经理指着PPT里规整的架构图说“这个模块应该很简单”&#xff0c;而开发负责人却皱着眉头指出&#xff1a;“你画的…

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

Excalidraw与OpenTelemetry链路追踪结合

Excalidraw 与 OpenTelemetry 链路追踪的可视化融合实践 在一次深夜排障中&#xff0c;团队盯着 Jaeger 界面上密密麻麻的调用链发愁&#xff1a;一个简单的用户请求竟横跨了十几个服务&#xff0c;嵌套层级深得像迷宫。虽然数据齐全&#xff0c;但没人能快速说清“到底哪一环…

作者头像 李华