python+AI高速公路收费系统

核心内容摘要

Nginx缓存002篇【20260225】
Fish Speech-1.5企业级应用:电商商品介绍自动化语音生成案例

用Neo4j和G.V()可视化攻击图谱,加固你的网络安全

.NET程序员外包项目救星原生JS大文件传输系统附前后端核心代码兄弟作为在杭州接外包的老.NET程序员太懂你现在的处境了——甲方爸爸要20G大文件上传还要兼容IE8预算卡得死死的网上代码全是“断头路”出了问题连个问的人都没有。

别慌我去年接了个类似项目熬了三个月啃下的原生JSASP.NET WebForm全栈方案今天全盘托出保证你能直接拿给客户演示合同签得比隔壁老王还快

方案核心专治甲方“奇葩需求”

功能全覆盖甲方看了直点头20G级大文件传输分片上传5MB/片断点续传SQL Server存进度关浏览器/重启电脑不丢。

文件夹层级保留递归遍历文件系统后端按/文件夹/子文件路径存储IE8用“伪路径元数据”方案兜底。

加密传输存储前端AES加密分片密钥动态生成后端SM4解密存储满足甲方“数据安全”要求。

非打包下载流式传输逐个文件几万文件也不卡支持“文件夹结构树”展示。

全浏览器兼容IE8隐藏inputFlash模拟、Edge/Chrome/Firefox原生API、信创国产浏览器龙芯/红莲花。

成本可控100元预算搞定原生JS实现0商业授权费用开源库CryptoJS代码直接嵌入Vue3项目。

轻量级依赖仅需Vue

CryptoJS、Axios无额外费用。

IIS免费部署Windows自带的IIS服务器E盘空间足够20G文件分片存E盘。

技术支持合同签完不跑路提供完整源码包前端后端SQL脚本导入就能跑。

免费远程调试用TeamViewer帮你连客户服务器解决“上传到一半卡住”的玄学问题。

群里

NET程序员互助QQ群374992201遇到坑直接甩日志截图老司机带你改代码。

前端核心代码Vue3 原生JS兼容IE

文件夹上传组件Vue3import { ref, onMounted } from vue; import CryptoJS from crypto-js; import axios from axios; import $ from jquery; // 兼容IE8的jQuery需npm install jquery // 全局变量 const uploadTasks ref([]); // 上传任务列表 const chunkSize 5 * 1024 * 1024; // 5MB分片兼容IE8内存 const aesKey CryptoJS.lib.WordArray.random(

.toString(); // 动态生成AES密钥后端需同步 let currentTaskId ; // 当前任务ID // 生命周期 onMounted(() { checkResumeTasks(); // 启动时检查未完成任务 }); // 核心方法 // 选择文件夹现代浏览器 const selectFolder () { fileInput.value.click(); }; // 处理文件选择兼容IE8 const handleFileSelect (e) { const files e.target.files; if (!files.length) return; // 生成唯一任务ID时间戳随机数 currentTaskId upload_${Date.now()}_${Math.random().toString(

.substr(2,

}; // 遍历文件生成上传任务IE8用伪路径 const newTasks Array.from(files).map(file ({ taskId: currentTaskId, fileName: file.name, filePath: /folder_${currentTaskId}/${file.webkitRelativePath || file.name}, // IE8用name代替路径 totalSize: file.size, uploadedSize: 0, progress: 0, status: 等待上传, chunkIndex: 0, totalChunks: Math.ceil(file.size / chunkSize) })); uploadTasks.value newTasks; startUpload(newTasks[0]); // 自动开始第一个任务 }; // 开始上传单个任务核心逻辑 const startUpload async (task) { if (task.status ! 等待上传 task.status ! 失败) return; //

恢复断点进度从SQL Server查进度 const dbProgress await getProgressFromDb(task.taskId); if (dbProgress) { task.chunkIndex dbProgress.ChunkIndex; task.uploadedSize dbProgress.UploadedSize; task.progress (dbProgress.UploadedSize / task.totalSize *

.toFixed(

; task.status 继续上传; } //

分片上传循环直到传完所有片 while (task.chunkIndex task.totalChunks) { const start task.chunkIndex * chunkSize; const end Math.min(start chunkSize, task.totalSize); const chunk task.file.slice(start, end); // IE8需用file.slice //

前端AES加密分片保护传输 const encryptedChunk CryptoJS.AES.encrypt( CryptoJS.lib.WordArray.create(await readFile(chunk)), aesKey, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 } ).toString(); //

构造FormData兼容IE8 const formData new FormData(); formData.append(taskId, task.taskId); formData.append(chunkIndex, task.chunkIndex); formData.append(totalChunks, task.totalChunks); formData.append(filePath, task.filePath); formData.append(chunk, new Blob([encryptedChunk])); try { //

调用ASP.NET后端上传接口本地IIS const res await axios.post(http://localhost:8080/UploadHandler.ashx?actionchunk, formData, { headers: { Content-Type: multipart/form-data }, onUploadProgress: (e) { // 计算上传速度MB/s const speed (e.loaded - task.uploadedSize) / (e.timeStamp - (task.lastTime || Date.now())) / 1024; task.speed speed.toFixed(

; task.lastTime e.timeStamp; } }); //

更新任务进度前端后端同步 task.chunkIndex; task.uploadedSize chunk.size; task.progress (task.uploadedSize / task.totalSize *

.toFixed(

; // 保存进度到SQL Server断点续传关键 await saveProgressToDb({ taskId: task.taskId, chunkIndex: task.chunkIndex, uploadedSize: task.uploadedSize }); //

上传完成清除进度提示成功 if (task.chunkIndex task.totalChunks) { task.progress 100; task.status 上传成功; localStorage.removeItem(upload_${task.taskId}); ElMessage.success(${task.fileName} 上传成功); } } catch (err) { task.status 失败; ElMessage.error(${task.fileName} 上传失败${err.response?.data?.msg || 网络错误}); break; } } }; // 重试上传任务失败后点击重试 const retryUpload (task) { task.chunkIndex 0; task.uploadedSize 0; task.progress 0; task.status 等待上传; localStorage.removeItem(upload_${task.taskId}); startUpload(task); }; // 格式化文件大小B→MB/GB新手友好 const formatSize (size) { if (size 1024 **

return ${(size / 1024 **

.toFixed(

} GB; if (size 1024 **

return ${(size / 1024 **

.toFixed(

} MB; return ${(size /

.toFixed(

} KB; }; // 读取文件内容兼容IE8返回ArrayBuffer const readFile (file) { return new Promise((resolve) { const reader new FileReader(); reader.onload (e) resolve(e.target.result); reader.readAsArrayBuffer(file); }); }; // 检查是否有未完成的上传任务从SQL Server恢复 const checkResumeTasks async () { // 调用后端接口/UploadHandler.ashx?actionresume const res await axios.get(http://localhost:8080/UploadHandler.ashx?actionresume); if (res.data.length) { uploadTasks.value res.data; ElMessage.warning(检测到未完成的上传任务是否继续); } }; // 查询数据库进度调用ASP.NET后端接口 const getProgressFromDb async (taskId) { try { const res await axios.get(http://localhost:8080/UploadHandler.ashx?actionprogresstaskId${taskId}); return res.data ? { ChunkIndex: res.data.ChunkIndex, UploadedSize: res.data.UploadedSize } : null; } catch (err) { return null; } }; // 保存进度到数据库调用ASP.NET后端接口 const saveProgressToDb async (progress) { try { await axios.post(http://localhost:8080/UploadHandler.ashx?actionsave-progress, progress); } catch (err) { console.error(保存进度失败:, err); } }; /* 样式略参考前文Vue示例适配IE8的div布局 */

后端核心代码ASP.NET WebForm C#

分片上传处理程序UploadHandler.ashx// UploadHandler.ashx.cspublicclassUploadHandler:IHttpHandler,IRequiresSessionState{publicvoidProcessRequest(HttpContextcontext){context.Response.ContentTypeapplication/json;stringactioncontext.Request.Params[action];switch(action){casechunk:// 上传分片HandleChunkUpload(context);break;casemerge:// 合并分片HandleMergeChunks(context);break;caseprogress:// 查询进度HandleProgressQuery(context);break;caseresume:// 恢复任务HandleResumeTasks(context);break;}}privatevoidHandleChunkUpload(HttpContextcontext){try{//

解析前端传参stringtaskIdcontext.Request.Params[taskId];intchunkIndexint.Parse(context.Request.Params[chunkIndex]);inttotalChunksint.Parse(context.Request.Params[totalChunks]);stringfilePathcontext.Request.Params[filePath];HttpPostedFilechunkFilecontext.Request.Files[chunk];//

解密分片AES→SM4byte[]chunkContentReadAllBytes(chunkFile.InputStream);byte[]decryptedChunkAesDecrypt(chunkContent,GetAesKey());// 从数据库获取AES密钥byte[]sm4EncryptedChunkSm4Encrypt(decryptedChunk,GetSm4Key());// SM4加密存储//

保存分片到E盘服务器路径stringsavePath$E:/FileStorage/{filePath}/{chunkIndex};Directory.CreateDirectory(Path.GetDirectoryName(savePath));File.WriteAllBytes(savePath,sm4EncryptedChunk);//

记录进度到SQL ServerSaveProgressToDb(taskId,chunkIndex,totalChunks,filePath,chunkFile.ContentLength);context.Response.Write(JsonConvert.SerializeObject(new{code200,msg分片上传成功}));}catch(Exceptionex){context.Response.Write(JsonConvert.SerializeObject(new{code500,msg$分片上传失败{ex.Message}}));}}privatevoidHandleMergeChunks(HttpContextcontext){stringtaskIdcontext.Request.Params[taskId];stringfilePathcontext.Request.Params[filePath];try{//

查询所有分片从SQL ServervarchunksGetChunksByTaskId(taskId);//

合并分片到E盘按顺序合并stringmergedPath$E:/FileStorage/{filePath}/merged_{taskId};using(FileStreamfsnewFileStream(mergedPath,FileMode.Create)){foreach(varchunkinchunks.OrderBy(cc.ChunkIndex)){byte[]chunkDataFile.ReadAllBytes($E:/FileStorage/{filePath}/{chunk.ChunkIndex});fs.Write(chunkData,0,chunkData.Length);File.Delete($E:/FileStorage/{filePath}/{chunk.ChunkIndex});// 删除临时分片}}//

清理SQL Server进度记录DeleteProgressFromDb(taskId);context.Response.Write(JsonConvert.SerializeObject(new{code200,msg合并成功,pathmergedPath}));}catch(Exceptionex){context.Response.Write(JsonConvert.SerializeObject(new{code500,msg$合并失败{ex.Message}}));}}privatevoidSaveProgressToDb(stringtaskId,intchunkIndex,inttotalChunks,stringfilePath,longuploadedSize){using(SqlConnectionconnnewSqlConnection(Serverlocalhost;DatabaseFileDB;User Idsa;Password123456;)){conn.Open();stringsql IF NOT EXISTS (SELECT * FROM UploadProgress WHERE TaskId TaskId AND ChunkIndex ChunkIndex) INSERT INTO UploadProgress (TaskId, ChunkIndex, TotalChunks, FilePath, UploadedSize) VALUES (TaskId, ChunkIndex, TotalChunks, FilePath, UploadedSize) ELSE UPDATE UploadProgress SET ChunkIndex ChunkIndex, UploadedSize UploadedSize WHERE TaskId TaskId AND ChunkIndex ChunkIndex;using(SqlCommandcmdnewSqlCommand(sql,conn)){cmd.Parameters.AddWithValue(TaskId,taskId);cmd.Parameters.AddWithValue(ChunkIndex,chunkIndex);cmd.Parameters.AddWithValue(TotalChunks,totalChunks);cmd.Parameters.AddWithValue(FilePath,filePath);cmd.Parameters.AddWithValue(UploadedSize,uploadedSize);cmd.ExecuteNonQuery();}}}// 其他辅助方法AesDecrypt、Sm4Encrypt、GetChunksByTaskId等略需实现SM4加解密和数据库查询}

数据库脚本SQL Server-- 创建数据库CREATEDATABASEFileDB;GO-- 使用数据库USEFileDB;GO-- 上传进度表记录分片上传状态CREATETABLEUploadProgress(IdINTIDENTITY(1,

PRIMARYKEY,TaskId NVARCHAR(

NOTNULL,-- 任务ID如upload_1620000000_abc123ChunkIndexINTNOTNULL,-- 已上传分片索引从0开始TotalChunksINTNOTNULL,-- 总分片数FilePath NVARCHAR(

NOTNULL,-- 文件存储路径如/folder_123/file.txtUploadedSizeBIGINTNOTNULL,-- 已上传大小字节UNIQUE(TaskId,ChunkIndex)-- 防止重复记录);

部署指南客户服务器IIS

前端部署Vue项目打包npm run build生成dist文件夹。

将dist文件夹复制到IIS网站根目录如C:\inetpub\wwwroot\FileUploader。

后端部署发布ASP.NET WebForm项目到IIS在Visual Studio中右键项目→发布→选择IIS服务器→设置物理路径如C:\inetpub\wwwroot\FileUploadBack。

配置web.config中的数据库连接字符串改为客户服务器的SQL Server信息。

服务器配置确保IIS应用程序池启用32位应用程序兼容IE8。

给E盘FileStorage文件夹授予IIS_IUSRS读写权限。

安装.NET Framework

8WebForm依赖。

找工作接单群学长真心话兄弟这套系统你拿去给客户演示甲方绝对挑不出刺——兼容IE

支持20G文件、加密传输、断点续传全搞定。

毕设答辩时老师看了直呼“专业”找工作时面试官看了直接给offer现在加群QQ374992201私聊我“外包”直接发你客户案例和合同模板群里还有一堆.NET大佬遇到问题直接甩代码一起接单一起赚附完整源码包链接百度网盘https://pan.baidu.com/s/1abc123defg提取码xyz123输入密码即可下载设置框架安装.NET Framework

4.

2https://dotnet.microsoft.com/en-us/download/dotnet-framework/net472框架选择

4.

2添加3rd引用编译项目NOSQLNOSQL无需任何配置可直接访问页面进行测试SQL使用IIS大文件上传测试推荐使用IIS以获取更高性能。

使用IIS Express小文件上传测试可以使用IIS Express创建数据库配置数据库连接信息检查数据库配置访问页面进行测试相关参考文件保存位置效果预览文件上传文件刷新续传支持离线保存文件进度在关闭浏览器刷新浏览器后进行不丢失仍然能够继续上传文件夹上传支持上传文件夹并保留层级结构同样支持进度信息离线保存刷新页面关闭页面重启系统不丢失上传进度。

下载示例下载完整示例

菠萝蜜在线观看免费高清电视剧荣耀-菠萝蜜在线观看免费高清电视剧荣耀应用

百度百家号客服电话人工服务

123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123