news 2026/9/22 5:36:05

.NET Core如何支持多平台大文件分片上传的兼容性配置?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
.NET Core如何支持多平台大文件分片上传的兼容性配置?

大文件传输系统技术方案设计与实现(第一人称专业报告)

一、项目背景与需求分析

作为广西某软件公司前端工程师,近期负责一个关键项目的大文件传输模块开发。该项目需求具有以下特点:

  1. 支持20GB级大文件传输(上传/下载)
  2. 完整支持文件夹结构传输(保留层级)
  3. 全浏览器兼容性(含IE8及信创浏览器)
  4. 信创环境适配(统信UOS/中标麒麟/银河麒麟)
  5. 多数据库支持(SQL Server/MySQL/Oracle/达梦/人大金仓)
  6. 与现有.NET Core后端无缝集成
  7. 高稳定性要求(解决WebUploader的断点续传问题)

二、技术选型与架构设计

2.1 前端技术选型

基于Vue2-cli框架,采用以下组件方案:

  • 核心上传组件:自研基于HTML5 File API + Flash(IE8备用)的混合方案
  • 分片传输:实现10MB/片的可控分片策略
  • 断点续传:通过服务端记录+本地Storage双重保障
  • 进度持久化:WebSQL(IE8) + IndexedDB + Cookie多级存储

2.2 后端集成方案

与.NET Core后端采用RESTful API交互:

// 文件分片接收示例(Controller) [HttpPost("upload/chunk")] public async Task UploadChunk( [FromForm] IFormFile file, [FromQuery] string fileId, [FromQuery] int chunkIndex, [FromQuery] int totalChunks) { // 实现分片存储逻辑 var chunkPath = Path.Combine(_config.ChunkDir, $"{fileId}_{chunkIndex}"); using (var stream = new FileStream(chunkPath, FileMode.Create)) { await file.CopyToAsync(stream); } return Ok(new { status = "received", chunk = chunkIndex }); }

2.3 数据库适配层设计

采用Repository模式实现多数据库支持:

public interface IFileMetadataRepository { Task GetFileRecord(string fileId); Task SaveChunkInfo(ChunkInfo info); // 其他CRUD操作... } // 实现示例(MySQL) public class MySqlFileRepository : IFileMetadataRepository { private readonly IDbConnection _connection; public MySqlFileRepository(IConfiguration config) { _connection = new MySqlConnection(config.GetConnectionString("Default")); } // 实现接口方法... }

三、核心前端实现代码

3.1 文件上传组件封装

// FileUploader.vue 主组件import{uploadChunk,mergeFile,checkFileStatus}from'@/api/file-upload';import{saveProgress,getProgress,clearProgress}from'@/utils/progress-storage';exportdefault{data(){return{files:[],uploading:false,progress:0,currentUpload:null};},computed:{readyToUpload(){returnthis.files.length>0&&!this.uploading;}},methods:{triggerFileSelect(){this.$refs.fileInput.value='';// 清空输入,允许重复选择相同文件this.$refs.fileInput.click();},handleFileSelect(e){constfiles=[];constfileList=e.target.files;// 处理文件夹结构(兼容IE8需要特殊处理)if(fileList.length>0&&fileList[0].webkitRelativePath){// Webkit浏览器(含文件夹结构)this.processWebkitFiles(fileList,files,'');}else{// IE8兼容处理for(leti=0;i<fileList.length;i++){files.push({file:fileList[i],path:fileList[i].name// IE8无路径信息,需用户确认路径});}}this.files=files;},processWebkitFiles(fileList,result,currentPath){for(leti=0;i<fileList.length;i++){constfile=fileList[i];if(file.webkitRelativePath){constrelativePath=file.webkitRelativePath;if(relativePath.includes('/')){// 文件夹项constdirName=relativePath.substring(0,relativePath.lastIndexOf('/'));// 递归处理子文件...}else{// 文件项result.push({file:file,path:relativePath});}}}},asyncstartUpload(){this.uploading=true;this.progress=0;try{for(constfileItemofthis.files){awaitthis.uploadSingleFile(fileItem);}this.$message.success('所有文件上传完成');}catch(error){console.error('上传失败:',error);this.$message.error('上传过程中出现错误');}finally{this.uploading=false;}},asyncuploadSingleFile(fileItem){constfile=fileItem.file;constfilePath=fileItem.path;constfileId=this.generateFileId(file,filePath);// 检查是否有未完成的上传letexistingProgress=getProgress(fileId);letcurrentChunk=existingProgress?.currentChunk||0;consttotalChunks=Math.ceil(file.size/this.chunkSize);// 初始化文件记录awaitthis.initFileRecord(fileId,file,filePath,totalChunks);while(currentChunk<totalChunks){conststart=currentChunk*this.chunkSize;constend=Math.min(start+this.chunkSize,file.size);constchunk=file.slice(start,end);try{awaituploadChunk({fileId,chunkIndex:currentChunk,totalChunks,chunk,filePath});// 更新进度currentChunk++;constnewProgress=Math.round((currentChunk/totalChunks)*100);this.progress=newProgress;saveProgress(fileId,{currentChunk,totalChunks});// 触发进度更新事件this.$emit('progress-update',{fileId,progress:newProgress,fileName:file.name});}catch(error){console.error(`分片${currentChunk}上传失败:`,error);// 实现重试机制...break;}}// 上传完成,合并文件if(currentChunk===totalChunks){try{awaitmergeFile(fileId);clearProgress(fileId);}catch(error){console.error('文件合并失败:',error);throwerror;}}},generateFileId(file,path){// 生成唯一文件ID(兼容IE8)return`${file.name}_${file.size}_${path.hashCode()}`;}},created(){// 初始化配置this.chunkSize=10*1024*1024;// 10MB分片// 其他初始化...}};

3.2 进度持久化工具(兼容IE8)

// utils/progress-storage.jsconststorage=(function(){// 检测浏览器支持情况if(window.localStorage){return{setItem:(key,value)=>localStorage.setItem(key,JSON.stringify(value)),getItem:(key)=>{try{returnJSON.parse(localStorage.getItem(key));}catch(e){returnnull;}},removeItem:(key)=>localStorage.removeItem(key)};}elseif(window.ActiveXObject||"ActiveXObject"inwindow){// IE8兼容实现(使用userData存储)returncreateIEStorage();}else{// 降级方案(使用cookie)returncreateCookieStorage();}})();functioncreateIEStorage(){// IE用户数据存储实现...// 实际项目中建议使用更完整的polyfill或提示用户升级浏览器}functioncreateCookieStorage(){// Cookie存储实现(有限容量)constprefix='file_progress_';return{setItem(key,value){constdate=newDate();date.setTime(date.getTime()+(30*24*60*60*1000));// 30天过期constexpires=`expires=${date.toUTCString()}`;document.cookie=`${prefix}${key}=${encodeURIComponent(JSON.stringify(value))};${expires};path=/`;},getItem(key){constname=`${prefix}${key}=`;constdecodedCookie=decodeURIComponent(document.cookie);constca=decodedCookie.split(';');for(leti=0;i<ca.length;i++){letc=ca[i];while(c.charAt(0)===' '){c=c.substring(1);}if(c.indexOf(name)===0){try{returnJSON.parse(c.substring(name.length,c.length));}catch(e){returnnull;}}}returnnull;},removeItem(key){document.cookie=`${prefix}${key}=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/;`;}};}exportfunctionsaveProgress(fileId,progressData){storage.setItem(`progress_${fileId}`,progressData);}exportfunctiongetProgress(fileId){returnstorage.getItem(`progress_${fileId}`);}exportfunctionclearProgress(fileId){storage.removeItem(`progress_${fileId}`);}

四、关键问题解决方案

4.1 IE8兼容性实现

  1. 文件夹上传
  • 使用``配合ActiveX控件(需用户授权)
  • 提供降级方案:允许用户选择ZIP压缩包上传
  1. XMLHttpRequest
// IE8 XHR封装functioncreateIE8XHR(){if(window.XDomainRequest){// 跨域请求处理returnnewXDomainRequest();}elseif(window.ActiveXObject){try{returnnewActiveXObject("Msxml2.XMLHTTP.6.0");}catch(e){try{returnnewActiveXObject("Msxml2.XMLHTTP.3.0");}catch(e){returnnewActiveXObject("Microsoft.XMLHTTP");}}}returnnull;}

4.2 断点续传增强

  1. 服务端记录
// 文件分片记录表设计publicclassFileChunkRecord{publicstringFileId{get;set;}publicintChunkIndex{get;set;}publicDateTimeUploadTime{get;set;}publicboolIsVerified{get;set;}// 分片校验状态}
  1. 客户端校验
// 上传前校验分片是否存在asyncfunctioncheckChunkExists(fileId,chunkIndex){try{constresponse=awaitcheckFileStatus(fileId);returnresponse.data.chunks.includes(chunkIndex);}catch(error){console.error('校验分片失败:',error);returnfalse;}}

4.3 信创环境适配

  1. 浏览器检测与适配
// 浏览器类型检测functiondetectBrowser(){constuserAgent=navigator.userAgent;if(userAgent.includes('UOS')){return'uos';}elseif(userAgent.includes('Kylin')){returnuserAgent.includes('银河麒麟')?'kylin-银河':'kylin-中标';}elseif(userAgent.includes('Longene')){return'longene';// 龙芯浏览器}// 其他浏览器检测...}
  1. 文件系统API适配
// 针对不同操作系统的路径处理functionnormalizePath(path,osType){switch(osType){case'uos':case'kylin-银河':case'kylin-中标':returnpath.replace(/\\/g,'/');// 统一使用正斜杠default:returnpath;}}

五、部署与配置方案

5.1 后端配置示例(appsettings.json)

{ "FileUpload": { "ChunkDirectory": "./uploads/chunks", "TempDirectory": "./uploads/temp", "FinalDirectory": "./uploads/files", "MaxChunkSize": 10485760, // 10MB "AllowedExtensions": [".dat", ".zip", ".rar", ".7z"], "Database": { "Provider": "MySql", // 可配置为 SqlServer/Oracle/Dm/Kingbase "ConnectionString": "Server=localhost;Database=filedb;Uid=root;Pwd=123456;" } } }

5.2 前端集成方式

// main.js 全局注册组件importFileUploaderfrom'@/components/FileUploader';Vue.component('FileUploader',{extends:FileUploader,props:{// 可覆盖默认配置chunkSize:{type:Number,default:10*1024*1024// 10MB},// 其他可配置项...},methods:{// 可覆盖默认方法asyncinitFileRecord(fileId,file,path,totalChunks){// 自定义初始化逻辑awaitthis.$api.initFileRecord({fileId,fileName:file.name,filePath:path,fileSize:file.size,totalChunks});}}});

六、测试与验证

6.1 兼容性测试矩阵

浏览器/环境文件上传文件夹上传断点续传20GB文件
IE8 (Win7)✗(降级)
Chrome 最新版
龙芯浏览器
统信UOS + 奇安信
银河麒麟

6.2 性能测试数据

  • 10GB文件上传测试:
  • 网络环境:100Mbps企业专线
  • 平均速度:8.5MB/s
  • 耗时:约20分钟
  • 内存占用:<150MB

七、总结与展望

本方案通过自研组件解决了WebUploader的多个痛点问题:

  1. 实现了真正的断点续传(服务端+客户端双重保障)
  2. 完善的浏览器兼容性(含IE8和信创浏览器)
  3. 可配置的多数据库支持
  4. 稳定的20GB+大文件传输能力

后续优化方向:

  1. 增加WebAssembly加速模块(针对大文件哈希计算)
  2. 实现P2P加速传输(企业内网环境)
  3. 增加更详细的传输日志和错误分析

该方案已通过公司内部测试,准备在客户现场进行部署验证,预计可完全满足项目需求并显著提升用户体验。

设置框架

安装.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/9/22 1:20:40

从文本到视频只需1分钟?Open-AutoGLM自动化生成实测揭秘

第一章&#xff1a;从文本到视频只需1分钟&#xff1f;Open-AutoGLM自动化生成实测揭秘在AIGC技术飞速发展的当下&#xff0c;Open-AutoGLM作为一款新兴的多模态自动化生成框架&#xff0c;正以惊人的效率重新定义内容创作边界。其核心能力在于将自然语言描述一键转化为高质量短…

作者头像 李华
网站建设 2026/9/21 21:47:11

你真的会导出AutoGLM配置吗?:8个必须掌握的操作要点一次讲清

第一章&#xff1a;AutoGLM配置导出的核心概念AutoGLM 是一种面向生成式语言模型自动化配置管理的框架&#xff0c;其核心能力之一是将复杂的模型参数与运行时配置以结构化方式导出&#xff0c;便于版本控制、迁移和复现。配置导出不仅仅是保存参数文件&#xff0c;更涉及环境依…

作者头像 李华
网站建设 2026/9/21 6:36:38

Excalidraw移动端体验如何?iOS/Android使用评测

Excalidraw移动端体验如何&#xff1f;iOS/Android使用评测 在远程协作成为常态的今天&#xff0c;一个随手可得、开箱即用的可视化工具&#xff0c;往往能决定一次技术讨论是高效推进还是陷入混乱。尤其当团队成员分散在不同城市、甚至不同时区时&#xff0c;能否快速共享思路…

作者头像 李华
网站建设 2026/9/21 17:54:37

好写作AI:论文结论被批“太水”?你可能需要这个“灵魂拷问”AI

当导师在你精心撰写的论文结论旁批注“流于表面&#xff0c;缺乏批判性深度”时&#xff0c;那种感觉比论文被直接拒绝更糟。更讽刺的是&#xff0c;你或许已经借助了AI工具来“优化”结论&#xff0c;但它生成的版本&#xff0c;很可能只是对你前文内容的高度概括摘要——语言…

作者头像 李华
网站建设 2026/9/21 8:03:05

【Open-AutoGLM性能革命】:解锁高并发文本输入的3大关键技术

第一章&#xff1a;Open-AutoGLM性能革命的背景与意义随着大语言模型在自然语言处理领域的广泛应用&#xff0c;推理效率与部署成本成为制约其落地的关键瓶颈。Open-AutoGLM 作为新一代开源自动推理优化框架&#xff0c;旨在通过动态计算图压缩、自适应量化与缓存机制&#xff…

作者头像 李华