【一个武汉刚毕业大学生的2G文件上传渡劫记从这能行到真香的码农变形记】妈我电脑风扇转得比光谷转盘还响了“我冲着客厅大喊手里攥着刚泡好的周黑鸭藕片眼睛死死盯着屏幕上那个卡在99%的进度条。作为江汉大学计算机系刚毕业的菜鸟码农”我万万没想到自己接的第一个自学项目就栽在了大文件上传这个长江大桥上。第一幕初生牛犊不怕虎光谷步行街式自信不就是上传个2G的文件吗百度一搜全是方案我叼着鸭脖自信满满地打开GitHub结果被满屏的英文文档吓得差点把辣油滴到键盘上WebUploader看着像老式公交车的仪表盘注释全是此处应有注释.jpgPlupload文档里居然有兼容IE6这种上古神兽的说明就像武汉公交还有无人售票的标识Uppy界面倒是时尚但配置项多得像户部巷的小吃摊我甚至看到了支持WebTorrent这种我连听都没听过的选项最终我选了resumable.js就因为它有个中文Demo而且作者头像是个二次元妹子后来发现是AI生成的就像光谷的网红奶茶店其实是个快招品牌。第二幕Vue2与大文件的热干面式纠缠为什么我的分片上传会变成’随机上传’我盯着控制台里乱序的chunk编号突然意识到问题可能出在// 我的天才代码武昌口音注释uploadChunk(chunk){// 居然用时间戳当key就像用热干面的芝麻酱当密码constkeyDate.now()Math.random();this.$axios.post(/api/upload,{chunk:chunk.file,key:key,// 每次请求的key都不一样服务器当然找不到对应的分片index:chunk.index});}更惨的是跨浏览器兼容性测试Chrome像光谷的地铁说走就走Firefox像公交2号线偶尔会卡在螃蟹岬Edge像共享单车看着能用但总有点小毛病IE11直接显示你的浏览器已过时就像你妈说你’该找对象了’其实是我根本没写polyfill第三幕.NET Core后端的户部巷式拥堵当第一个2G文件真的传到服务器时我的IIS直接表演了原地爆炸// 最初的API天真得像以为光谷不堵车[HttpPost(upload)]publicasyncTaskUpload(IFormFilefile){varpathPath.Combine(uploads,file.FileName);using(varstreamnewFileStream(path,FileMode.Create)){awaitfile.CopyToAsync(stream);// 内存占用直接飙到3G就像把整碗热干面汤喝光}returnOk();}测试时发现上传100M文件成功像坐轮渡过江上传500M文件超时像等643路公交上传1G文件IIS崩溃像长江大桥大雾封桥上传2G文件服务器蓝屏像武汉夏天突然停电更搞笑的是错误处理// 我的佛系错误处理汉口话版try{// 上传逻辑...}catch(Exceptionex){// 反正用户也看不懂错误信息就像我分不清武昌和汉口的公交站returnStatusCode(500,服务器说它累了就像你加班到晚上10点);}第四幕SQL Server的东湖式迷茫客户说要记录上传历史我盯着那台只有500G硬盘的云服务器突然意识到问题-- 最初的设计天真得像以为东湖永远不干CREATETABLEUploadRecords(IdINTIDENTITYPRIMARYKEY,FileName NVARCHAR(255),FileSizeBIGINT,-- 2G文件就是2147483648字节UploadTimeDATETIME,StatusTINYINT-- 0上传中 1完成 2失败-- 没有索引没有分区没有外键就像武汉的共享单车没有头盔);测试时发现插入100条记录0.01秒像坐地铁过江插入1000条记录0.5秒像坐公交过江插入10000条记录5秒像步行过长江大桥查询未完成的任务全表扫描像在户部巷找特定的一家热干面摊第五幕绝地求生方案光谷特供版经过三天三夜的谷歌搜索和两包精武鸭脖我制定了新方案前端改造汉味优化改用uppy.io至少文档是2024年的不像某些武汉公交时刻表实现真正的分片上传// 用localStorage存储上传状态武汉方言注释constsaveState(fileId,chunks){localStorage.setItem(upload:${fileId},JSON.stringify(chunks));// 就像把热干面的配方记在手机备忘录里};添加进度条动画用CSS让进度条跳《龙船调》实现断点续传就像武汉公交司机说莫慌下一班马上来后端自救东湖方案用MemoryMappedFile处理大文件// 合并分片时不再吃内存就像分批次吃周黑鸭using(varmmfMemoryMappedFile.CreateFromFile(final.dat,FileMode.Create)){for(inti0;itotalChunks;i){varchunkPathPath.Combine(uploads,fileHash,${i}.part);using(varchunkStreamnewFileStream(chunkPath,FileMode.Open)){// 内存映射文件操作...就像把长江分成小溪流}}}添加速率限制// 防止客户端疯狂上传就像限制过早摊主不能同时煮20碗热干面app.Use(async(context,next){varclientIpcontext.Connection.RemoteIpAddress;varrateLimitKey$upload:{clientIp};// 用简单的内存计数器实际应该用Redis但我还不会if(HttpContext.Items[rateLimitKey]isintcountcount100){context.Response.StatusCode429;awaitcontext.Response.WriteAsync(慢点兄弟武汉话叫莫慌);return;}HttpContext.Items[rateLimitKey](count??0)1;awaitnext();});异步处理文件合并// 用Hangfire后台任务就像让外卖小哥先送其他单_backgroundJobClient.Schedule(()MergeFile(fileHash),TimeSpan.FromMinutes(1)// 延迟1分钟合并就像等公交时先抽根烟);数据库优化户部巷方案改用FILESTREAM存储大文件元数据就像把鸭脖真空包装添加索引CREATEINDEXIX_UploadRecords_StatusONUploadRecords(Status);-- 现在查询未完成的任务只要0.1秒就像坐地铁过江分表策略-- 按月份分表就像把不同季节的衣服分开放CREATETABLEUploadRecords_202406(-- 结构同主表);终幕测试日的疯狂光谷限定版当那个2.1G的《武汉城市宣传片》终于显示上传成功时我激动得把鸭脖骨头卡在键盘里——至少这次没把服务器宕机只是让整个办公室的鼠标都变得黏糊糊的就像光谷步行街的地砖。客户反馈IE11进度条显示NaN%我微笑.jpg 并默默在Nginx配置里加了if ($http_user_agent ~* MSIE) { return 403; }360浏览器会弹出此网站可能存在风险我这锅武汉不背Edge浏览器上传速度比Chrome慢30%我可能是武汉的网不好…吧但不管怎样当我看到SQL Server里那条完整的上传记录时我知道自己终于跨过了这道长江大桥。现在每当路过光谷软件园我都会对着那些亮着灯的窗户说“看那个曾经被2G文件折磨得死去活来的菜鸟现在也能写大文件上传了”虽然声音小得像武汉夏天的蚊子叫设置框架安装.NET Framework 4.7.2https://dotnet.microsoft.com/en-us/download/dotnet-framework/net472框架选择4.7.2添加3rd引用编译项目NOSQLNOSQL无需任何配置可直接访问页面进行测试SQL使用IIS大文件上传测试推荐使用IIS以获取更高性能。使用IIS Express小文件上传测试可以使用IIS Express创建数据库配置数据库连接信息检查数据库配置访问页面进行测试相关参考文件保存位置效果预览文件上传文件刷新续传支持离线保存文件进度在关闭浏览器刷新浏览器后进行不丢失仍然能够继续上传文件夹上传支持上传文件夹并保留层级结构同样支持进度信息离线保存刷新页面关闭页面重启系统不丢失上传进度。下载完整示例下载完整示例