先用ps后用dw做网站,西安网站建设eliwe,飞沐网站设计,我的小程序入口大文件上传解决方案
作为一个同样接外包接到手软的.NET老油条#xff0c;我完全理解你既要兼容IE8又要20G文件上传还要100块预算的无理要求。来#xff0c;给你整一套饿不死套餐#xff01;
前端实现 - 兼容IE8的土味方案 穷逼版大文件上传/* 祖传…大文件上传解决方案作为一个同样接外包接到手软的.NET老油条我完全理解你既要兼容IE8又要20G文件上传还要100块预算的无理要求。来给你整一套饿不死套餐前端实现 - 兼容IE8的土味方案穷逼版大文件上传 /* 祖传CSS兼容IE8 */ .upload-area { border: 2px dashed #ccc; padding: 20px; text-align: center; margin: 20px; } .progress-container { width: 100%; background-color: #f5f5f5; margin: 10px 0; } .progress-bar { height: 20px; background-color: #4CAF50; width: 0%; } .file-list { margin: 20px; border: 1px solid #ddd; padding: 10px; } 大文件上传兼容IE8版 拖放文件或文件夹到此处 或 选择文件/文件夹 等待上传文件... 开始上传 暂停 继续 加密方式 SM4国密 AES // 兼容IE8的JSON if (typeof JSON undefined) { document.write(scriptsrchttps://cdnjs.cloudflare.com/ajax/libs/json2/20150503/json2.min.js\/script); } // 上传队列 var uploadQueue []; var currentUpload null; var chunkSize 5 * 1024 * 1024; // 5MB分块 // 文件选择处理 document.getElementById(fileInput).addEventListener(change, function(e) { handleFiles(e.target.files); }); // 拖放处理 var dropArea document.getElementById(dropArea); dropArea.addEventListener(dragover, function(e) { e.preventDefault(); dropArea.style.borderColor #4CAF50; }); dropArea.addEventListener(dragleave, function() { dropArea.style.borderColor #ccc; }); dropArea.addEventListener(drop, function(e) { e.preventDefault(); dropArea.style.borderColor #ccc; handleFiles(e.dataTransfer.files); }); // 处理文件选择 function handleFiles(files) { var fileList document.getElementById(fileList); fileList.innerHTML ; for (var i 0; i files.length; i) { var file files[i]; var fileItem document.createElement(div); fileItem.innerHTML file.name ( formatFileSize(file.size) ); fileList.appendChild(fileItem); uploadQueue.push({ file: file, progress: 0, status: pending }); } } // 开始上传 function startUpload() { if (uploadQueue.length 0) return; currentUpload uploadQueue[0]; uploadFile(currentUpload); } // 上传文件 function uploadFile(fileItem) { var file fileItem.file; var fileId generateFileId(file); var totalChunks Math.ceil(file.size / chunkSize); // 从本地存储加载断点 var resumeChunk localStorage.getItem(resume_ fileId) || 0; // 上传分块 for (var chunkIndex resumeChunk; chunkIndex totalChunks; chunkIndex) { if (fileItem.status paused) break; var start chunkIndex * chunkSize; var end Math.min(start chunkSize, file.size); var chunk file.slice(start, end); // 加密分块伪代码 var encryptedChunk encryptChunk( chunk, document.getElementById(encryptionType).value, document.getElementById(encryptionKey).value ); var formData new FormData(); formData.append(fileId, fileId); formData.append(chunkIndex, chunkIndex); formData.append(totalChunks, totalChunks); formData.append(fileName, file.name); formData.append(filePath, file.webkitRelativePath || ); formData.append(fileSize, file.size); formData.append(chunkData, encryptedChunk); formData.append(encryption, document.getElementById(encryptionType).value); // AJAX上传兼容IE8 var xhr new XMLHttpRequest(); xhr.open(POST, /api/upload/chunk, false); // 同步上传IE8不支持Promise xhr.upload.onprogress function(e) { var loaded chunkIndex * chunkSize e.loaded; fileItem.progress Math.round((loaded / file.size) * 100); updateProgress(); }; xhr.onreadystatechange function() { if (xhr.readyState 4) { if (xhr.status 200) { // 保存断点 localStorage.setItem(resume_ fileId, chunkIndex 1); if (chunkIndex totalChunks - 1) { // 合并文件 mergeFile(fileId); fileItem.status completed; uploadQueue.shift(); startUpload(); } } else { console.error(上传失败:, xhr.responseText); } } }; xhr.send(formData); } } // 暂停上传 function pauseUpload() { if (currentUpload) { currentUpload.status paused; } } // 继续上传 function resumeUpload() { if (currentUpload currentUpload.status paused) { currentUpload.status uploading; uploadFile(currentUpload); } } // 合并文件 function mergeFile(fileId) { var xhr new XMLHttpRequest(); xhr.open(POST, /api/upload/merge, false); xhr.setRequestHeader(Content-Type, application/json); xhr.onreadystatechange function() { if (xhr.readyState 4 xhr.status 200) { console.log(文件合并成功:, xhr.responseText); localStorage.removeItem(resume_ fileId); } }; xhr.send(JSON.stringify({ fileId: fileId, encryption: document.getElementById(encryptionType).value })); } // 生成文件ID function generateFileId(file) { return file.name _ file.size _ file.lastModifiedDate.getTime(); } // 加密分块伪实现 function encryptChunk(chunk, algorithm, key) { // 实际项目中应该使用Web Crypto API或相应库 console.log(使用 algorithm 加密分块密钥:, key); return chunk; } // 更新进度显示 function updateProgress() { var progressBars document.querySelectorAll(.progress-bar); for (var i 0; i progressBars.length; i) { progressBars[i].style.width uploadQueue[i].progress %; } } // 格式化文件大小 function formatFileSize(bytes) { if (bytes 0) return 0 B; var k 1024; var sizes [B, KB, MB, GB, TB]; var i Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) sizes[i]; }后端实现 - ASP.NET WebForm版FileUploadHandler.ashx%WebHandlerLanguageC#ClassFileUploadHandler%usingSystem;usingSystem.Web;usingSystem.IO;usingSystem.Collections.Generic;usingSystem.Linq;publicclassFileUploadHandler:IHttpHandler{publicvoidProcessRequest(HttpContextcontext){context.Response.ContentTypeapplication/json;try{stringactioncontext.Request[action];switch(action){caseupload_chunk:HandleChunkUpload(context);break;casemerge_file:HandleMergeFile(context);break;default:context.Response.Write({\error\:\无效操作\});break;}}catch(Exceptionex){context.Response.Write({\error\:\ex.Message\});}}privatevoidHandleChunkUpload(HttpContextcontext){stringfileIdcontext.Request[fileId];intchunkIndexint.Parse(context.Request[chunkIndex]);inttotalChunksint.Parse(context.Request[totalChunks]);stringfileNamecontext.Request[fileName];stringfilePathcontext.Request[filePath];longfileSizelong.Parse(context.Request[fileSize]);stringencryptioncontext.Request[encryption];HttpPostedFilechunkDatacontext.Request.Files[chunkData];// 保存分块stringchunkDirGetChunkDir(fileId);if(!Directory.Exists(chunkDir)){Directory.CreateDirectory(chunkDir);}stringchunkPathPath.Combine(chunkDir,chunkIndex.ToString().chunk);chunkData.SaveAs(chunkPath);// 保存断点信息SaveResumeInfo(fileId,chunkIndex1,totalChunks);context.Response.Write({\success\:true});}privatevoidHandleMergeFile(HttpContextcontext){stringfileIdcontext.Request[fileId];stringencryptioncontext.Request[encryption];// 获取分块信息varresumeInfoGetResumeInfo(fileId);if(resumeInfonull){thrownewException(找不到文件断点信息);}stringchunkDirGetChunkDir(fileId);stringfileNamePath.GetFileNameWithoutExtension(resumeInfo.FileName);stringfileExtPath.GetExtension(resumeInfo.FileName);// 创建目标文件stringsaveDirPath.Combine(AppDomain.CurrentDomain.BaseDirectory,Uploads);if(!string.IsNullOrEmpty(resumeInfo.FilePath)){saveDirPath.Combine(saveDir,resumeInfo.FilePath);}if(!Directory.Exists(saveDir)){Directory.CreateDirectory(saveDir);}stringsavePathPath.Combine(saveDir,fileNamefileExt);using(FileStreamfsnewFileStream(savePath,FileMode.Create)){// 合并所有分块for(inti0;iresumeInfo.TotalChunks;i){stringchunkPathPath.Combine(chunkDir,i.chunk);byte[]chunkDataFile.ReadAllBytes(chunkPath);// 解密数据伪实现byte[]decryptedDataDecryptChunk(chunkData,encryption);fs.Write(decryptedData,0,decryptedData.Length);// 删除临时分块File.Delete(chunkPath);}}// 删除分块目录Directory.Delete(chunkDir);// 清理断点信息ClearResumeInfo(fileId);context.Response.Write({\success\:true, \filePath\:\savePath.Replace(\\,/)\});}privatestringGetChunkDir(stringfileId){returnPath.Combine(AppDomain.CurrentDomain.BaseDirectory,Temp,fileId);}privatevoidSaveResumeInfo(stringfileId,intchunkIndex,inttotalChunks){varinfonewResumeInfo{FileIdfileId,ChunkIndexchunkIndex,TotalChunkstotalChunks,LastUpdateDateTime.Now};stringinfoPathPath.Combine(GetChunkDir(fileId),resume.info);File.WriteAllText(infoPath,Newtonsoft.Json.JsonConvert.SerializeObject(info));}privateResumeInfoGetResumeInfo(stringfileId){stringinfoPathPath.Combine(GetChunkDir(fileId),resume.info);if(File.Exists(infoPath)){returnNewtonsoft.Json.JsonConvert.DeserializeObject(File.ReadAllText(infoPath));}returnnull;}privatevoidClearResumeInfo(stringfileId){stringinfoPathPath.Combine(GetChunkDir(fileId),resume.info);if(File.Exists(infoPath)){File.Delete(infoPath);}}privatebyte[]DecryptChunk(byte[]encryptedData,stringalgorithm){// 实际项目中应该使用SM4/AES解密returnencryptedData;}publicboolIsReusable{get{returntrue;}}privateclassResumeInfo{publicstringFileId{get;set;}publicstringFileName{get;set;}publicstringFilePath{get;set;}publicintChunkIndex{get;set;}publicintTotalChunks{get;set;}publicDateTimeLastUpdate{get;set;}}}数据库设计 - 乞丐版CREATETABLE[dbo].[FileUploadRecords](50NOTNULL,255NOTNULL,512NULL,[FileSize][bigint]NOTNULL,512NOTNULL,20NULL,20NULL,50NULL,[UploadTime][datetime]NOTNULL,[CompleteTime][datetime]NULL,CONSTRAINT[PK_FileUploadRecords]PRIMARYKEYCLUSTERED([Id]ASC))部署指南 - 手把手教学前端部署把HTML文件扔到IIS网站目录确保启用静态内容后端部署在Visual Studio中发布WebForm项目部署到IIS确保应用程序池使用.NET 4.0权限设置给Uploads和Temp目录添加IIS_IUSRS写权限IE8兼容性在IIS中添加MIME类型.json application/json在页面添加X-UA-Compatible标签注意事项加密部分实际项目中应该使用正规加密库这里只是伪实现性能问题IE8下同步上传会阻塞页面用户体验极差但甲方爸爸要兼容没办法安全性记得在前端和后端都做文件类型检查防止上传恶意文件预算问题100块真的做不了什么建议跟甲方商量加点钱最后忠告下次接单前先谈好兼容性要求IE8真的该淘汰了尽量说服客户升级100块的项目别指望7x24支持除非你想饿死加群374992201里面有大佬可以教你如何合理报价设置框架安装.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创建数据库配置数据库连接信息检查数据库配置访问页面进行测试相关参考文件保存位置效果预览文件上传文件刷新续传支持离线保存文件进度在关闭浏览器刷新浏览器后进行不丢失仍然能够继续上传文件夹上传支持上传文件夹并保留层级结构同样支持进度信息离线保存刷新页面关闭页面重启系统不丢失上传进度。下载完整示例下载完整示例