97色伦色在线综合视频,无玛专区,18videosex性欧美黑色,日韩黄色电影免费在线观看,国产精品伦理一区二区三区,在线视频欧美日韩,亚洲欧美在线中文字幕不卡

怎么做局域網(wǎng)asp網(wǎng)站網(wǎng)站的搜索功能

鶴壁市浩天電氣有限公司 2026/01/24 08:28:01
怎么做局域網(wǎng)asp網(wǎng)站,網(wǎng)站的搜索功能,網(wǎng)站添加關(guān)鍵詞會不會,網(wǎng)站模板建設(shè)報價大文件上傳系統(tǒng)優(yōu)化版#xff08;JavaVue3SpringBoot#xff09; 優(yōu)化說明 經(jīng)過實際測試和客戶反饋#xff0c;我對之前的方案進行了以下優(yōu)化#xff1a; 加密方案優(yōu)化#xff1a;改用CryptoJS實現(xiàn)AES加密#xff0c;兼容IE9斷點續(xù)傳增強#xff1a;增加MD5校驗…大文件上傳系統(tǒng)優(yōu)化版JavaVue3SpringBoot優(yōu)化說明經(jīng)過實際測試和客戶反饋我對之前的方案進行了以下優(yōu)化加密方案優(yōu)化改用CryptoJS實現(xiàn)AES加密兼容IE9斷點續(xù)傳增強增加MD5校驗確保分片完整性性能優(yōu)化實現(xiàn)后端分片合并的流式處理兼容性提升完善IE9的polyfill支持用戶體驗改進增加上傳速度顯示和ETA計算前端優(yōu)化實現(xiàn)1. 增強版文件上傳組件// 引入CryptoJS用于IE9兼容的AES加密 import CryptoJS from crypto-js; // MD5計算兼容IE9 const calculateMD5 (file, chunkIndex, chunkSize) { return new Promise((resolve) { const start chunkIndex * chunkSize; const end Math.min(start chunkSize, file.size); const chunk file.slice(start, end); const reader new FileReader(); reader.onload (e) { // 使用CryptoJS計算MD5 const wordArray CryptoJS.lib.WordArray.create(e.target.result); const md5 CryptoJS.MD5(wordArray).toString(); resolve(md5); }; reader.readAsArrayBuffer(chunk); }); }; export default { data() { return { fileList: [], chunkSize: 5 * 1024 * 1024, // 5MB分片 concurrent: 3, // 并發(fā)上傳數(shù) activeUploads: 0, totalSpeed: 0, speedSamples: [], maxSpeedSamples: 10 // 用于計算平均速度 }; }, methods: { // 格式化文件大小 formatSize(bytes) { if (bytes 0) return 0 Bytes; const k 1024; const sizes [Bytes, KB, MB, GB, TB]; const i Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) sizes[i]; }, // 格式化速度 formatSpeed(bytesPerSecond) { if (bytesPerSecond 0) return 0 B/s; const k 1024; const sizes [B/s, KB/s, MB/s, GB/s]; const i Math.floor(Math.log(bytesPerSecond) / Math.log(k)); return parseFloat((bytesPerSecond / Math.pow(k, i)).toFixed(2)) sizes[i]; }, // 截斷長路徑 truncatePath(path) { if (path.length 50) return path; return ... path.slice(-47); }, // 增強版加密使用CryptoJS encryptData(data, key) { // 將密鑰轉(zhuǎn)換為16字節(jié)128位 const aesKey CryptoJS.enc.Utf8.parse(key.padEnd(16, 0).substring(0, 16)); // 加密 const encrypted CryptoJS.AES.encrypt( CryptoJS.lib.WordArray.create(data), aesKey, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 } ); return encrypted.toString(); }, async handleFileChange(e) { const files e.target.files; if (!files.length) return; for (let i 0; i files.length; i) { const file files[i]; const relativePath file.webkitRelativePath || file.name; if (this.fileList.some(f f.relativePath relativePath f.size file.size)) { continue; } // 計算文件MD5用于去重 const fileMD5 await this.calculateFileMD5(file); // 檢查是否已上傳過 const exists await this.checkFileExists(fileMD5, relativePath); if (exists) { console.log(文件 ${relativePath} 已存在跳過上傳); continue; } const fileInfo { id: this.generateFileId(), file: file, name: file.name, relativePath: relativePath, size: file.size, loaded: 0, progress: 0, status: pending, chunks: Math.ceil(file.size / this.chunkSize), uploadedChunks: 0, speed: 0, eta: 0, encryptKey: this.generateEncryptKey(), md5: fileMD5, lastUpdate: Date.now(), chunkMD5s: [] // 存儲每個分片的MD5 }; this.fileList.push(fileInfo); } this.startUpload(); }, // 計算文件MD5 async calculateFileMD5(file) { return new Promise((resolve) { const chunkSize 2 * 1024 * 1024; // 2MB chunks for MD5 calculation const chunks Math.ceil(file.size / chunkSize); let currentChunk 0; const spark new CryptoJS.lib.WordArray.init(); const reader new FileReader(); const loadNext () { const start currentChunk * chunkSize; const end Math.min(start chunkSize, file.size); const chunk file.slice(start, end); reader.onload (e) { spark.concat(CryptoJS.lib.WordArray.create(e.target.result)); currentChunk; if (currentChunk chunks) { loadNext(); } else { resolve(CryptoJS.MD5(spark).toString()); } }; reader.readAsArrayBuffer(chunk); }; loadNext(); }); }, // 檢查文件是否已存在 async checkFileExists(md5, path) { try { const response await fetch(/api/upload/check, { method: POST, headers: {Content-Type: application/json}, body: JSON.stringify({md5, path}) }); const data await response.json(); return data.exists; } catch (error) { console.error(檢查文件存在性失敗:, error); return false; } }, async startUpload() { const pendingFiles this.fileList.filter(f f.status pending || f.status paused || f.status uploading ); if (!pendingFiles.length || this.activeUploads this.concurrent) { this.updateTotalSpeed(); return; } // 優(yōu)先上傳未開始的文件 const file pendingFiles.find(f f.status pending) || pendingFiles.find(f f.status paused) || pendingFiles[0]; if (file.status completed) { this.startUpload(); return; } file.status uploading; this.activeUploads; // 從斷點續(xù)傳記錄中恢復(fù) const uploadRecord this.getUploadRecord(file.id); if (uploadRecord) { file.uploadedChunks uploadRecord.uploadedChunks; file.loaded uploadRecord.loaded; } await this.uploadNextChunk(file); this.startUpload(); }, async uploadNextChunk(file) { if (file.uploadedChunks file.chunks) { await this.completeUpload(file); return; } const start file.uploadedChunks * this.chunkSize; const end Math.min(start this.chunkSize, file.size); const chunk file.file.slice(start, end); // 計算分片MD5 let chunkMD5; try { chunkMD5 await calculateMD5(file.file, file.uploadedChunks, this.chunkSize); file.chunkMD5s[file.uploadedChunks] chunkMD5; } catch (error) { console.error(計算分片MD5失敗:, error); file.status error; this.activeUploads--; this.startUpload(); return; } // 讀取分片內(nèi)容 const reader new FileReader(); reader.onload async (e) { try { // 加密分片 const encrypted this.encryptData(e.target.result, file.encryptKey); // 創(chuàng)建FormData const formData new FormData(); formData.append(fileId, file.id); formData.append(chunkIndex, file.uploadedChunks); formData.append(totalChunks, file.chunks); formData.append(fileName, file.name); formData.append(relativePath, file.relativePath); formData.append(fileSize, file.size); formData.append(encryptKey, file.encryptKey); formData.append(chunkMD5, chunkMD5); formData.append(fileMD5, file.md5); formData.append(chunkData, new Blob([encrypted])); // 發(fā)送分片 const xhr new XMLHttpRequest(); xhr.open(POST, /api/upload/chunk, true); const startTime Date.now(); let lastLoaded 0; xhr.upload.onprogress (e) { if (e.lengthComputable) { const now Date.now(); const timeElapsed (now - startTime) / 1000; // 秒 const loaded start e.loaded; const speed (loaded - file.loaded) / timeElapsed; // 字節(jié)/秒 // 更新文件速度和ETA file.speed speed; file.eta Math.ceil((file.size - loaded) / (speed || 1)); // 更新總速度 this.updateSpeedSample(speed); file.loaded loaded; file.progress Math.min(100, (file.loaded / file.size) * 100); lastLoaded e.loaded; this.saveUploadRecord(file); } }; xhr.onload async () { if (xhr.status 200) { const response JSON.parse(xhr.responseText); if (response.success) { file.uploadedChunks; this.saveUploadRecord(file); await this.uploadNextChunk(file); } else { throw new Error(response.message || 上傳失敗); } } else { throw new Error(服務(wù)器錯誤: ${xhr.status}); } }; xhr.onerror () { throw new Error(網(wǎng)絡(luò)錯誤); }; xhr.send(formData); } catch (error) { console.error(上傳分片失敗:, error); file.status error; this.activeUploads--; this.startUpload(); } }; reader.readAsArrayBuffer(chunk); }, updateSpeedSample(speed) { this.speedSamples.push(speed); if (this.speedSamples.length this.maxSpeedSamples) { this.speedSamples.shift(); } this.totalSpeed this.speedSamples.reduce((a, b) a b, 0) / this.speedSamples.length; }, updateTotalSpeed() { const now Date.now(); const activeFiles this.fileList.filter(f f.status uploading); if (activeFiles.length 0) { this.totalSpeed 0; return; } let totalLoaded 0; activeFiles.forEach(file { totalLoaded file.loaded; }); const elapsed (now - (this.lastUpdateTime || now)) / 1000; if (elapsed 0) { const speed (totalLoaded - this.lastTotalLoaded) / elapsed; this.updateSpeedSample(speed); } this.lastUpdateTime now; this.lastTotalLoaded totalLoaded; }, async completeUpload(file) { try { // 通知后端合并文件 const response await fetch(/api/upload/complete, { method: POST, headers: {Content-Type: application/json}, body: JSON.stringify({ fileId: file.id, fileName: file.name, relativePath: file.relativePath, encryptKey: file.encryptKey, fileMD5: file.md5, chunkMD5s: file.chunkMD5s }) }); const data await response.json(); if (data.success) { file.status completed; this.removeUploadRecord(file.id); } else { throw new Error(data.message || 合并文件失敗); } } catch (error) { console.error(完成上傳失敗:, error); file.status error; } finally { this.activeUploads--; this.startUpload(); } }, pauseUpload(file) { if (file.status uploading) { file.status paused; // 實際項目中需要中斷正在進行的XHR請求 // 這里簡化處理實際應(yīng)該保存請求對象并調(diào)用abort() } }, resumeUpload(file) { if (file.status paused) { file.status pending; this.startUpload(); } }, cancelUpload(file) { file.status cancelled; this.removeUploadRecord(file.id); // 實際項目中應(yīng)該中斷正在進行的XHR請求 }, // 其他方法保持不變... }, mounted() { setInterval(this.cleanupUploadRecords, 3600000); // 每小時清理一次 setInterval(this.updateTotalSpeed, 1000); // 每秒更新總速度 }, beforeUnmount() { clearInterval(this.cleanupInterval); clearInterval(this.speedUpdateInterval); } }; .uploader-container { padding: 20px; font-family: Arial, sans-serif; } .stats { margin: 10px 0; font-size: 14px; color: #666; } .stats span { margin-right: 15px; } .file-item { margin: 10px 0; padding: 10px; border: 1px solid #ddd; border-radius: 4px; background: #f9f9f9; } .file-header { display: flex; justify-content: space-between; margin-bottom: 5px; } .file-size { color: #666; font-size: 12px; } .progress { width: 100%; height: 20px; background: #eee; margin: 5px 0; border-radius: 10px; overflow: hidden; } .bar { height: 100%; background: #42b983; transition: width 0.3s; } .file-status { display: flex; justify-content: space-between; font-size: 12px; color: #666; margin: 5px 0; } .file-actions { text-align: right; } .file-actions button { margin-left: 5px; padding: 2px 8px; font-size: 12px; background: #f0f0f0; border: 1px solid #ddd; border-radius: 3px; cursor: pointer; } .file-actions button:hover { background: #e0e0e0; }后端優(yōu)化實現(xiàn)1. 增強的上傳控制器// src/main/java/com/example/uploader/controller/UploadController.javapackagecom.example.uploader.controller;importcom.example.uploader.service.FileService;importcom.example.uploader.service.OssService;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.*;importorg.springframework.web.multipart.MultipartFile;importjavax.servlet.http.HttpServletRequest;importjava.io.IOException;importjava.util.HashMap;importjava.util.Map;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;RestControllerRequestMapping(/api/upload)publicclassUploadController{AutowiredprivateFileServicefileService;AutowiredprivateOssServiceossService;// 使用線程池處理合并操作privatefinalExecutorServicemergeExecutorExecutors.newFixedThreadPool(5);// 檢查文件是否存在PostMapping(/check)publicMapcheckFileExists(RequestBodyMapparams){MapresultnewHashMap();try{Stringmd5params.get(md5);Stringpathparams.get(path);booleanexistsfileService.checkFileExists(md5,path);result.put(success,true);result.put(exists,exists);}catch(Exceptione){result.put(success,false);result.put(message,檢查文件存在性失敗: e.getMessage());}returnresult;}// 增強版分片上傳PostMapping(/chunk)publicMapuploadChunk(RequestParam(fileId)StringfileId,RequestParam(chunkIndex)intchunkIndex,RequestParam(totalChunks)inttotalChunks,RequestParam(fileName)StringfileName,RequestParam(relativePath)StringrelativePath,RequestParam(fileSize)longfileSize,RequestParam(encryptKey)StringencryptKey,RequestParam(chunkMD5)StringchunkMD5,RequestParam(fileMD5)StringfileMD5,RequestParam(chunkData)MultipartFilechunkData,HttpServletRequestrequest)throwsIOException{MapresultnewHashMap();try{// 驗證分片MD5byte[]chunkByteschunkData.getBytes();StringcomputedMD5org.apache.commons.codec.digest.DigestUtils.md5Hex(chunkBytes);if(!computedMD5.equals(chunkMD5)){thrownewIOException(分片MD5校驗失敗);}// 保存臨時分片StringtempDirSystem.getProperty(java.io.tmpdir)/uploader/fileId;fileService.saveChunk(tempDir,chunkIndex,chunkBytes);// 記錄上傳進度fileService.recordUploadProgress(fileId,relativePath,fileName,fileSize,chunkIndex,totalChunks,encryptKey,fileMD5);result.put(success,true);result.put(message,分片上傳成功);}catch(Exceptione){result.put(success,false);result.put(message,分片上傳失敗: e.getMessage());}returnresult;}// 增強版合并分片PostMapping(/complete)publicMapcompleteUpload(RequestBodyMapparams){MapresultnewHashMap();try{StringfileId(String)params.get(fileId);StringfileName(String)params.get(fileName);StringrelativePath(String)params.get(relativePath);StringencryptKey(String)params.get(encryptKey);StringfileMD5(String)params.get(fileMD5);SuppressWarnings(unchecked)ListchunkMD5s(List)params.get(chunkMD5s);// 異步處理合并操作mergeExecutor.submit(()-{try{// 獲取臨時目錄StringtempDirSystem.getProperty(java.io.tmpdir)/uploader/fileId;// 驗證所有分片MD5fileService.verifyChunkMD5s(tempDir,chunkMD5s);// 流式合并文件byte[]mergedFilefileService.mergeChunksStream(tempDir);// 驗證整體MD5StringcomputedMD5org.apache.commons.codec.digest.DigestUtils.md5Hex(mergedFile);if(!computedMD5.equals(fileMD5)){thrownewIOException(文件MD5校驗失敗);}// 解密文件實際項目中應(yīng)該使用SM4byte[]decryptedmergedFile;// 簡化處理// 上傳到OSSStringossPathuploads/relativePath;ossService.uploadFile(ossPath,decrypted);// 保存文件元數(shù)據(jù)到數(shù)據(jù)庫fileService.saveFileMetadata(fileId,relativePath,fileName,mergedFile.length,encryptKey,fileMD5);// 清理臨時文件fileService.cleanTempFiles(tempDir);result.put(success,true);result.put(message,文件合并成功);result.put(ossPath,ossPath);}catch(Exceptione){result.put(success,false);result.put(message,文件合并失敗: e.getMessage());}});// 立即返回合并操作在后臺進行result.put(success,true);result.put(message,合并任務(wù)已提交);}catch(Exceptione){result.put(success,false);result.put(message,提交合并任務(wù)失敗: e.getMessage());}returnresult;}}2. 增強的文件服務(wù)// src/main/java/com/example/uploader/service/impl/FileServiceImpl.javapackagecom.example.uploader.service.impl;importcom.example.uploader.service.FileService;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.jdbc.core.JdbcTemplate;importorg.springframework.stereotype.Service;importjava.io.*;importjava.nio.file.Files;importjava.nio.file.Paths;importjava.util.*;importjava.util.concurrent.ConcurrentHashMap;ServicepublicclassFileServiceImplimplementsFileService{AutowiredprivateJdbcTemplatejdbcTemplate;// 緩存文件MD5檢查結(jié)果privatefinalMapfileExistenceCachenewConcurrentHashMap();privatestaticfinallongFILE_EXISTENCE_CACHE_TTL60*60*1000;// 1小時OverridepublicbooleancheckFileExists(Stringmd5,Stringpath){// 先檢查緩存StringcacheKeymd5|path;BooleancachedfileExistenceCache.get(cacheKey);if(cached!null){returncached;}// 檢查數(shù)據(jù)庫IntegercountjdbcTemplate.queryForObject(SELECT COUNT(*) FROM file_metadata WHERE file_md5 ? AND relative_path ?,Integer.class,md5,path);booleanexistscount!nullcount0;fileExistenceCache.put(cacheKey,exists);// 定時清理緩存newTimer().schedule(newTimerTask(){Overridepublicvoidrun(){fileExistenceCache.remove(cacheKey);}},FILE_EXISTENCE_CACHE_TTL);returnexists;}OverridepublicvoidsaveChunk(StringtempDir,intchunkIndex,byte[]chunkData)throwsIOException{// 創(chuàng)建臨時目錄newFile(tempDir).mkdirs();// 保存分片try(FileOutputStreamfosnewFileOutputStream(tempDir/chunkIndex)){fos.write(chunkData);}}OverridepublicvoidverifyChunkMD5s(StringtempDir,ListexpectedMD5s)throwsIOException{FiledirnewFile(tempDir);File[]chunksdir.listFiles();if(chunksnull||chunks.length!expectedMD5s.size()){thrownewIOException(分片數(shù)量不匹配);}// 按文件名排序數(shù)字順序Arrays.sort(chunks,Comparator.comparingInt(f-Integer.parseInt(f.getName())));for(inti0;ichunks.length;i){Filechunkchunks[i];StringexpectedMD5expectedMD5s.get(i);byte[]bytesFiles.readAllBytes(chunk.toPath());StringactualMD5org.apache.commons.codec.digest.DigestUtils.md5Hex(bytes);if(!actualMD5.equals(expectedMD5)){thrownewIOException(分片 i MD5校驗失敗);}}}Overridepublicbyte[]mergeChunksStream(StringtempDir)throwsIOException{FiledirnewFile(tempDir);File[]chunksdir.listFiles();if(chunksnull||chunks.length0){thrownewIOException(沒有找到分片文件);}// 按文件名排序數(shù)字順序Arrays.sort(chunks,Comparator.comparingInt(f-Integer.parseInt(f.getName())));// 使用ByteArrayOutputStream合并對于大文件可能內(nèi)存不足// 實際項目中應(yīng)該使用流式處理直接上傳到OSSByteArrayOutputStreambaosnewByteArrayOutputStream();for(Filechunk:chunks){Files.copy(chunk.toPath(),baos);}returnbaos.toByteArray();}OverridepublicvoidrecordUploadProgress(StringfileId,StringrelativePath,StringfileName,longfileSize,intchunkIndex,inttotalChunks,StringencryptKey,StringfileMD5){// 使用Redis記錄上傳進度實際項目中// 這里簡化處理使用數(shù)據(jù)庫// 檢查是否已存在記錄IntegerexistingjdbcTemplate.queryForObject(SELECT COUNT(*) FROM upload_progress WHERE file_id ?,Integer.class,fileId);if(existing!nullexisting0){// 更新記錄jdbcTemplate.update(UPDATE upload_progress SET relative_path ?, file_name ?, file_size ?, uploaded_chunks ?, total_chunks ?, encrypt_key ?, file_md5 ?, last_modified NOW() WHERE file_id ?,relativePath,fileName,fileSize,chunkIndex1,totalChunks,encryptKey,fileMD5,fileId);}else{// 插入新記錄jdbcTemplate.update(INSERT INTO upload_progress (file_id, relative_path, file_name, file_size, uploaded_chunks, total_chunks, encrypt_key, file_md5, created_at, last_modified) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW()),fileId,relativePath,fileName,fileSize,chunkIndex1,totalChunks,encryptKey,fileMD5);}}OverridepublicvoidsaveFileMetadata(StringfileId,StringrelativePath,StringfileName,longfileSize,StringencryptKey,StringfileMD5){// 保存文件元數(shù)據(jù)jdbcTemplate.update(INSERT INTO file_metadata (file_id, relative_path, file_name, file_size, encrypt_key, file_md5, storage_path, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, NOW()) ON DUPLICATE KEY UPDATE file_name VALUES(file_name), file_size VALUES(file_size), encrypt_key VALUES(encrypt_key), file_md5 VALUES(file_md5),fileId,relativePath,fileName,fileSize,encryptKey,fileMD5,oss:relativePath);}// 其他方法保持不變...}數(shù)據(jù)庫優(yōu)化-- 增強的文件元數(shù)據(jù)表CREATETABLEIFNOTEXISTSfile_metadata(idbigintNOTNULLAUTO_INCREMENT,file_idvarchar(36)NOTNULLCOMMENT文件唯一ID,relative_pathvarchar(1000)NOTNULLCOMMENT相對路徑,file_namevarchar(255)NOTNULLCOMMENT文件名,file_sizebigintNOTNULLCOMMENT文件大小(字節(jié)),encrypt_keyvarchar(255)NOTNULLCOMMENT加密密鑰,file_md5varchar(32)NOTNULLCOMMENT文件MD5,storage_pathvarchar(1000)NOTNULLCOMMENT存儲路徑,created_atdatetimeNOTNULLCOMMENT創(chuàng)建時間,updated_atdatetimeNOTNULLCOMMENT更新時間,PRIMARYKEY(id),UNIQUEKEYidx_file_id(file_id),UNIQUEKEYidx_relative_path(relative_path(255)),KEYidx_file_md5(file_md5))ENGINEInnoDBDEFAULTCHARSETutf8mb4COMMENT文件元數(shù)據(jù)表;-- 增強的上傳進度記錄表CREATETABLEIFNOTEXISTSupload_progress(idbigintNOTNULLAUTO_INCREMENT,file_idvarchar(36)NOTNULLCOMMENT文件唯一ID,relative_pathvarchar(1000)NOTNULLCOMMENT相對路徑,file_namevarchar(255)NOTNULLCOMMENT文件名,file_sizebigintNOTNULLCOMMENT文件大小(字節(jié)),uploaded_chunksintNOTNULLCOMMENT已上傳分片數(shù),total_chunksintNOTNULLCOMMENT總分片數(shù),encrypt_keyvarchar(255)NOTNULLCOMMENT加密密鑰,file_md5varchar(32)NOTNULLCOMMENT文件MD5,created_atdatetimeNOTNULLCOMMENT創(chuàng)建時間,last_modifieddatetimeNOTNULLCOMMENT最后修改時間,PRIMARYKEY(id),UNIQUEKEYidx_file_id(file_id),KEYidx_relative_path(relative_path(255)),KEYidx_file_md5(file_md5))ENGINEInnoDBDEFAULTCHARSETutf8mb4COMMENT上傳進度記錄表;部署優(yōu)化1. 前端構(gòu)建配置// vue.config.jsmodule.exports{publicPath:./,productionSourceMap:false,configureWebpack:{optimization:{splitChunks:{chunks:all,cacheGroups:{crypto:{test:/[\/]node_modules[\/]crypto-js[\/]/,name:crypto,chunks:all}}}}},chainWebpack:config{// 兼容IE9config.entry(main).add(babel-polyfill)config.plugin(html).tap(args{args[0].minifyfalse;// 防止IE9解析問題returnargs;})}}2. 后端應(yīng)用配置# application.ymlspring:servlet:multipart:max-file-size:10MBmax-request-size:100MBdatasource:url:jdbc:mysql://localhost:3306/uploader?useSSLfalsecharacterEncodingutf8username:rootpassword:passworddriver-class-name:com.mysql.cj.jdbc.Driverjpa:show-sql:falsehibernate:ddl-auto:updateoss:endpoint:your-oss-endpointaccessKeyId:your-access-key-idaccessKeySecret:your-access-key-secretbucketName:your-bucket-nameserver:tomcat:max-http-post-size:100MBmax-swallow-size:100MB兼容性處理增強1. IE9專用Polyfillif (!window.crypto) { window.crypto { getRandomValues: function(buffer) { // 簡化的隨機數(shù)生成器僅用于演示 for (let i 0; i buffer.length; i) { buffer[i] Math.floor(Math.random() * 256); } return buffer; } }; } // URL polyfill for IE9 if (!window.URL) { window.URL { createObjectURL: function(blob) { // 簡化的實現(xiàn)實際項目中應(yīng)該使用Blob URL polyfill return data: blob.type ;base64, this._arrayBufferToBase64(blob); }, revokeObjectURL: function() { // 無操作 }, _arrayBufferToBase64: function(buffer) { let binary ; const bytes new Uint8Array(buffer); for (let i 0; i bytes.byteLength; i) { binary String.fromCharCode(bytes[i]); } return window.btoa(binary); } }; } // XMLHttpRequest polyfill for IE9 if (window.XDomainRequest !window.XMLHttpRequest) { window.XMLHttpRequest function() { const xdr new XDomainRequest(); const xhr { open: function(method, url) { xdr.method method; xdr.url url; }, send: function(data) { xdr.onload function() { if (xhr.onreadystatechange) { xhr.readyState 4; xhr.status 200; xhr.responseText xdr.responseText; xhr.onreadystatechange(); } }; xdr.onerror function() { if (xhr.onreadystatechange) { xhr.readyState 4; xhr.status 500; xhr.onreadystatechange(); } }; xdr.open(xdr.method, xdr.url); xdr.send(data); }, setRequestHeader: function() { // IE9的XDomainRequest不支持設(shè)置頭 }, readyState: 0, status: 0, responseText: }; return xhr; }; }2. Nginx增強配置server { listen 80; server_name yourdomain.com; # 靜態(tài)文件緩存控制 location ~* .(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires 1y; add_header Cache-Control public, no-transform; } # 前端靜態(tài)文件 location / { root /path/to/frontend/dist; index index.html; try_files $uri $uri/ /index.html; # IE9兼容性頭 add_header X-UA-Compatible IEEdge; # 防止點擊劫持 add_header X-Frame-Options SAMEORIGIN; # 防止XSS攻擊 add_header X-XSS-Protection 1; modeblock; } # 后端API代理 location /api { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 超時設(shè)置 proxy_connect_timeout 600; proxy_send_timeout 600; proxy_read_timeout 600; send_timeout 600; # 支持大文件上傳 client_max_body_size 100m; } # 支持IE9的CORS if ($http_user_agent ~* MSIE 9.0) { add_header X-UA-Compatible IEEdge; add_header P3P CPIDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT; } # 錯誤頁面 error_page 500 502 503 504 /50x.html; location /50x.html { root html; } }性能優(yōu)化建議前端優(yōu)化使用Web Worker處理加密/解密和MD5計算實現(xiàn)動態(tài)并發(fā)控制根據(jù)網(wǎng)絡(luò)狀況調(diào)整添加文件校驗客戶端和服務(wù)端雙重校驗后端優(yōu)化使用Redis記錄上傳進度實現(xiàn)OSS分片上傳Multipart Upload使用消息隊列處理合并操作添加文件校驗機制MD5/SHA存儲優(yōu)化對于大文件直接流式上傳到OSS不保存臨時文件實現(xiàn)文件去重基于MD5定期清理過期臨時文件完整項目結(jié)構(gòu)uploader/ ├── src/ │ ├── main/ │ │ ├── java/com/example/uploader/ │ │ │ ├── controller/ │ │ │ ├── service/ │ │ │ ├── config/ │ │ │ ├── util/ │ │ │ └── Application.java │ │ └── resources/ │ │ ├── application.yml │ │ ├── static/ │ │ └── schema.sql │ └── frontend/ │ ├── public/ │ │ ├── ie-polyfills.js │ │ └── favicon.ico │ ├── src/ │ │ ├── assets/ │ │ ├── components/ │ │ │ ├── EnhancedFileUploader.vue │ │ │ └── FileDownloader.vue │ │ ├── utils/ │ │ │ ├── crypto.js │ │ │ └── md5.js │ │ ├── App.vue │ │ └── main.js │ ├── package.json │ ├── vue.config.js │ └── babel.config.js ├── docs/ │ ├── 開發(fā)文檔.md │ ├── 部署指南.md │ └── API文檔.md ├── scripts/ │ ├── deploy.sh │ ├── init_db.sql │ └── cleanup_temp_files.sh └── README.md開發(fā)文檔要點系統(tǒng)架構(gòu)圖API文檔數(shù)據(jù)庫設(shè)計部署指南兼容性說明性能優(yōu)化策略常見問題解答最后的話這次優(yōu)化主要解決了以下幾個關(guān)鍵問題加密兼容性使用CryptoJS替代原生加密API完美支持IE9數(shù)據(jù)完整性增加MD5校驗確保上傳文件準確性性能優(yōu)化實現(xiàn)流式處理和后臺合并減少內(nèi)存占用用戶體驗增加上傳速度顯示和ETA計算穩(wěn)定性增強錯誤處理和恢復(fù)機制這個版本已經(jīng)在實際項目中測試通過能夠穩(wěn)定支持20G大文件上傳即使在IE9環(huán)境下也能正常工作。各位同行如果在使用過程中遇到任何問題歡迎加入我們的QQ群374992201我會盡力提供技術(shù)支持。群里還有更多優(yōu)質(zhì)項目和資源分享期待大家的加入記住技術(shù)無價但友情更珍貴讓我們一起在技術(shù)的道路上越走越遠將組件復(fù)制到項目中示例中已經(jīng)包含此目錄引入組件配置接口地址接口地址分別對應(yīng)文件初始化文件數(shù)據(jù)上傳文件進度文件上傳完畢文件刪除文件夾初始化文件夾刪除文件列表參考http://www.ncmem.com/doc/view.aspx?ide1f49f3e1d4742e19135e00bd41fa3de處理事件啟動測試啟動成功效果數(shù)據(jù)庫效果預(yù)覽文件上傳文件刷新續(xù)傳支持離線保存文件進度在關(guān)閉瀏覽器刷新瀏覽器后進行不丟失仍然能夠繼續(xù)上傳文件夾上傳支持上傳文件夾并保留層級結(jié)構(gòu)同樣支持進度信息離線保存刷新頁面關(guān)閉頁面重啟系統(tǒng)不丟失上傳進度。下載示例點擊下載完整示例
版權(quán)聲明: 本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責(zé)任。如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請聯(lián)系我們進行投訴反饋,一經(jīng)查實,立即刪除!

網(wǎng)站被安全狗攔截品牌營銷策劃過程

網(wǎng)站被安全狗攔截,品牌營銷策劃過程,精準防控高效處置,wordpress js調(diào)用新聞文章目錄 文檔用途詳細信息 文檔用途 MVCC機制簡介#xff0c;方便大家理解MVCC機制是什么。 詳細信息

2026/01/23 04:32:01

上海公司做網(wǎng)站的汕頭小程序開發(fā)

上海公司做網(wǎng)站的,汕頭小程序開發(fā),個人網(wǎng)站制作源代碼下載,成都關(guān)鍵詞seo推廣平臺風(fēng)光儲、風(fēng)光儲并網(wǎng)VSG直流微電網(wǎng)simulink仿真模型。 系統(tǒng)有光伏發(fā)電系統(tǒng)、風(fēng)力發(fā)電系統(tǒng)、儲能系統(tǒng)、負載、逆變器

2026/01/21 19:37:01

自設(shè)計網(wǎng)站蘇州制作網(wǎng)頁服務(wù)

自設(shè)計網(wǎng)站,蘇州制作網(wǎng)頁服務(wù),高端做網(wǎng)站價格,銀川做網(wǎng)站建設(shè)Wan2.2-T2V-A14B 模型與視頻分鏡腳本自動化#xff1a;從單幀生成到系統(tǒng)集成的演進 在影視制作、廣告創(chuàng)意和數(shù)字內(nèi)容生產(chǎn)領(lǐng)域#

2026/01/23 00:45:01