技能管理体系:从技能盘点、技能树到刻意练习的完整指南
2026/10/21 3:59:41
作为山西某大型国企上市公司的项目负责人,我司目前承担着集团级大文件传输平台建设任务。客户群体涵盖部委、政府部门及大型央企,对系统安全性、稳定性及兼容性提出严苛要求。经详细调研,核心需求如下:
// file-uploader.vue 核心片段exportdefault{data(){return{chunkSize:10*1024*1024,// 10MB分片ws:null,progressMap:newMap()// 持久化进度存储}},methods:{// 初始化WebSocket连接(兼容IE8)initWebSocket(fileId){if(window.WebSocket){this.ws=newWebSocket(`wss://${location.host}/ws/upload/${fileId}`);}elseif(window.MozWebSocket){this.ws=newMozWebSocket(`wss://${location.host}/ws/upload/${fileId}`);}else{// IE8降级方案this.fallbackUpload(fileId);return;}this.ws.onmessage=(e)=>{constdata=JSON.parse(e.data);if(data.type==='progress'){this.progressMap.set(data.chunkId,data.percent);this.saveProgressToLocalStorage();}};},// 本地存储进度(兼容IE8)saveProgressToLocalStorage(){try{if(window.localStorage){localStorage.setItem('uploadProgress',JSON.stringify(Array.from(this.progressMap)));}else{// IE8使用userData存储constuserData=document.createElement('input');userData.addBehavior('#default#userData');userData.setAttribute('uploadProgress',JSON.stringify(Array.from(this.progressMap)));userData.save('FileUploadData');}}catch(e){console.error('Progress save failed:',e);}},// 文件分片上传(支持文件夹)asyncuploadFile(file,path=''){constfileId=this.generateFileId(file);consttotalChunks=Math.ceil(file.size/this.chunkSize);// 从本地恢复进度this.loadProgressFromLocalStorage(fileId);for(leti=0;i<totalChunks;i++){if(this.progressMap.has(`${fileId}-${i}`))continue;constchunk=file.slice(i*this.chunkSize,(i+1)*this.chunkSize);constformData=newFormData();formData.append('file',chunk);formData.append('chunkIndex',i);formData.append('totalChunks',totalChunks);formData.append('relativePath',path);try{awaitaxios.post(`/api/upload/${fileId}`,formData,{headers:{'X-Encryption-Type':'SM4'// 加密标识},onUploadProgress:(progressEvent)=>{constpercent=Math.round((progressEvent.loaded*100)/progressEvent.total);this.progressMap.set(`${fileId}-${i}`,percent);this.saveProgressToLocalStorage();}});}catch(e){console.error(`Chunk${i}upload failed`,e);throwe;}}// 通知服务端合并文件awaitaxios.post('/api/merge',{fileId,fileName:file.name,relativePath:path});},// 文件夹上传(递归处理)asyncuploadFolder(folderEntry,currentPath=''){constreader=folderEntry.createReader();constentries=awaitnewPromise((resolve)=>{reader.readEntries(resolve);});for(constentryofentries){if(entry.isFile){constfile=awaitnewPromise((resolve)=>{entry.file(resolve);});awaitthis.uploadFile(file,`${currentPath}/${entry.name}`);}elseif(entry.isDirectory){awaitthis.uploadFolder(entry,`${currentPath}/${entry.name}`);}}}}}// FileUploadController.java 核心片段@RestController@RequestMapping("/api")publicclassFileUploadController{@AutowiredprivateFileStorageServicestorageService;@AutowiredprivateEncryptionServiceencryptionService;// 文件分片上传@PostMapping("/upload/{fileId}")publicResponseEntity>uploadChunk(@PathVariableStringfileId,@RequestParam("file")MultipartFilefile,@RequestParamintchunkIndex,@RequestParaminttotalChunks,@RequestHeader("X-Encryption-Type")StringencryptionType){try{// 1. 解密处理byte[]decryptedData;if("SM4".equals(encryptionType)){decryptedData=encryptionService.sm4Decrypt(file.getBytes());}else{decryptedData=encryptionService.aesDecrypt(file.getBytes());}// 2. 存储分片StringchunkPath=storageService.storeChunk(fileId,chunkIndex,decryptedData,totalChunks);// 3. 返回进度信息Mapresponse=newHashMap<>();response.put("chunkIndex",chunkIndex);response.put("status","SUCCESS");returnResponseEntity.ok(response);}catch(Exceptione){returnResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(Collections.singletonMap("error",e.getMessage()));}}// 合并文件@PostMapping("/merge")publicResponseEntitymergeFile(@RequestBodyMergeRequestrequest){try{// 验证所有分片是否存在if(!storageService.allChunksExist(request.getFileId(),request.getTotalChunks())){returnResponseEntity.badRequest().body("Missing chunks");}// 合并文件StringfinalPath=storageService.mergeFile(request.getFileId(),request.getFileName(),request.getRelativePath());// 返回下载URLreturnResponseEntity.ok(finalPath);}catch(Exceptione){returnResponseEntity.internalServerError().body(e.getMessage());}}// WebSocket进度推送(IE8降级方案)@GetMapping("/ws/upload/{fileId}")publicWebSocketHandlerhandleWebSocket(@PathVariableStringfileId){returnsession->{// 实现自定义业务逻辑};}}// 国密加密实现publicclassSM4EncryptionServiceimplementsEncryptionService{privatestaticfinalStringSM4_KEY="your-32-byte-sm4-key";// 实际应从安全配置读取@Overridepublicbyte[]encrypt(byte[]data)throwsException{SM4Engineengine=newSM4Engine();PaddedBufferedBlockCiphercipher=newPaddedBufferedBlockCipher(newCBCBlockCipher(engine),newPKCS7Padding());byte[]keyBytes=SM4_KEY.getBytes(StandardCharsets.UTF_8);byte[]iv=newbyte[engine.getBlockSize()];// 实际应从安全配置读取cipher.init(true,newParametersWithIV(newKeyParameter(keyBytes),iv));byte[]output=newbyte[cipher.getOutputSize(data.length)];intlen=cipher.processBytes(data,0,data.length,output,0);len+=cipher.doFinal(output,len);returnArrays.copyOf(output,len);}@Overridepublicbyte[]decrypt(byte[]encryptedData)throwsException{// 实现解密逻辑(与encrypt对称)// ...}}基于集团需求,建议从以下维度评估供应商:
信创认证:
安全资质:
核心功能:
开发支持:
授权模式:
成功案例:
| 阶段 | 周期 | 交付物 |
|---|---|---|
| 需求确认 | 2周 | 详细需求规格说明书 |
| 技术选型 | 3周 | 供应商评估报告 |
| 原型开发 | 4周 | 可运行演示系统 |
| 信创适配 | 6周 | 全栈国产化环境验证 |
| 试点部署 | 2周 | 客户现场压力测试 |
| 全面推广 | 持续 | 集团级部署手册 |
技术风险:
合规风险:
商务风险:
本方案已充分考虑政府客户特有的安全合规要求,通过分层架构设计实现技术解耦,确保系统既能满足当前需求,又具备未来5年的技术演进能力。建议尽快启动供应商评估流程,确保在Q3前完成试点部署。
支持离线保存文件进度,在关闭浏览器,刷新浏览器后进行不丢失,仍然能够继续上传
支持上传文件夹并保留层级结构,同样支持进度信息离线保存,刷新页面,关闭页面,重启系统不丢失上传进度。
支持文件批量下载
文件下载支持离线保存进度信息,刷新页面,关闭页面,重启系统均不会丢失进度信息。
支持下载文件夹,并保留层级结构,不打包,不占用服务器资源。
下载完整示例