docker-selenium 浏览器镜像打标流程全解析:以 Selenium Grid 4.33.0 的 Chrome 123 发布记录为例
2026/10/9 5:23:59
——基于信创环境的SM4国密加密与FastDFS分布式存储集成
作为北京某国企技术负责人,我司承担的政府招投标项目需实现100GB级超大文件安全传输,并深度集成至现有JSP业务系统。核心需求包括:
| 组件类型 | 选型方案 | 国产化适配说明 |
|---|---|---|
| 前端框架 | Vue 2.6 + jQuery 1.12(IE8兼容) | 通过polyfill实现ES5兼容 |
| 分片上传 | 自定义实现(基于Blob API) | 兼容IE10+的File API回退方案 |
| 国密算法 | GMSSL 2.5(开源) | 编译WebAssembly模块供前端调用 |
| 服务端 | Spring Boot 2.7 + JSP | 通过Tomcat 9.0.x支持JSP |
| 分布式存储 | FastDFS 6.0 + Nginx | 扩展FastDFS插件支持SM4加密存储 |
| 数据库 | MyBatis-Plus + ShardingSphere | 支持多数据源动态切换 |
// SM4加密工具类(WebAssembly封装)classSM4Crypto{constructor(){this.module=null;this.initPromise=this._loadWasm();}async_loadWasm(){constresponse=awaitfetch('/static/sm4.wasm');constbuffer=awaitresponse.arrayBuffer();this.module=awaitWebAssembly.instantiate(buffer);returnthis.module;}asyncencryptChunk(chunk,key){awaitthis.initPromise;constencrypted=this.module.exports.sm4_encrypt(newUint8Array(chunk),newUint8Array(key.padEnd(32,'\0')));returnnewUint8Array(encrypted);}}// 文件夹上传处理器(递归遍历文件树)classFolderUploader{constructor(options){this.sm4=newSM4Crypto();this.chunkSize=10*1024*1024;// 10MB分片this.fileId=this._generateFileId();}async_uploadFile(file,relativePath=''){consttotalChunks=Math.ceil(file.size/this.chunkSize);constkey=awaitthis._fetchEncryptionKey();// 从服务端获取密钥for(leti=0;i<totalChunks;i++){constchunk=file.slice(i*this.chunkSize,(i+1)*this.chunkSize);constencrypted=awaitthis.sm4.encryptChunk(awaitchunk.arrayBuffer(),key);constformData=newFormData();formData.append('file',newBlob([encrypted]));formData.append('chunkIndex',i);formData.append('totalChunks',totalChunks);formData.append('fileId',this.fileId);formData.append('relativePath',relativePath);formData.append('fileName',file.name);formData.append('fileSize',file.size);await$.ajax({url:'/api/upload/chunk',type:'POST',data:formData,processData:false,contentType:false});}}asyncuploadFolder(folderEntry){constreader=folderEntry.createReader();constentries=awaitnewPromise(resolve=>reader.readEntries(resolve));for(constentryofentries){if(entry.isFile){awaitthis._uploadFile(awaitnewPromise(resolve=>entry.file(resolve)),entry.fullPath);}elseif(entry.isDirectory){awaitthis.uploadFolder(entry);// 递归处理子目录}}}}@RestController@RequestMapping("/api/upload")publicclassChunkUploadController{@AutowiredprivateFastDFSClientfastDFSClient;@Value("${sm4.key.path}")privateStringkeyPath;@PostMapping("/chunk")publicResponseEntityhandleChunk(@RequestParam("file")MultipartFilefile,@RequestParamLongchunkIndex,@RequestParamLongtotalChunks,@RequestParamStringfileId,@RequestParamStringrelativePath,@RequestParamStringfileName,@RequestParamLongfileSize){try{// 1. 解密分片(实际需调用GMSSL库)byte[]decrypted=decryptChunk(file.getBytes());// 2. 暂存分片到本地(FastDFS需整体上传,故先合并)PathtempDir=Paths.get("/tmp/chunks",fileId);Files.createDirectories(tempDir);Files.write(tempDir.resolve("chunk_"+chunkIndex),decrypted);// 3. 如果是最后一片,合并并上传FastDFSif(chunkIndex==totalChunks-1){PathmergedFile=mergeChunks(tempDir,fileId,fileSize);StringfastDFSPath=uploadToFastDFS(mergedFile,relativePath);saveToDatabase(fileId,fileName,relativePath,fastDFSPath,fileSize);returnResponseEntity.ok().body(Map.of("status","completed"));}returnResponseEntity.ok().body(Map.of("status","accepted"));}catch(Exceptione){returnResponseEntity.status(500).build();}}privateStringuploadToFastDFS(Pathfile,StringrelativePath)throwsException{// 扩展FastDFS客户端,支持SM4加密存储NameValuePair[]metaList=newNameValuePair[]{newNameValuePair("relative_path",relativePath),newNameValuePair("sm4_encrypted","true")};returnfastDFSClient.uploadFileWithMeta(file.toString(),metaList);}}// FastDFS存储插件扩展(伪代码)intstorage_upload_file_with_sm4(ConnectionInfo*pTrackerServer,ConnectionInfo*pStorageServer,constchar*local_filename,constchar*file_ext_name,NameValuePair*metadata){// 1. 读取文件并SM4加密std::ifstreamin(local_filename,std::ios::binary);std::ostringstream encrypted;SM4Encryptorsm4(get_sm4_key_from_metadata(metadata));sm4.encrypt(in,encrypted);// 2. 写入FastDFS存储节点StorageClientclient(pTrackerServer,pStorageServer);returnclient.upload_buffer(encrypted.str().c_str(),encrypted.str().size(),file_ext_name,metadata);}IE8兼容性:
XMLHttpRequest模拟分片上传(兼容性模式)100GB文件性能优化:
文件夹层级保留:
DirectoryEntry,记录relativePath信创数据库适配:
SELECT * FROM FILE_METADATA WHERE STORAGE_TYPE = 'FASTDFS' START WITH PARENT_ID IS NULL CONNECT BY PRIOR ID = PARENT_ID第一阶段(3周):
第二阶段(4周):
第三阶段(2周):
| 风险项 | 应对方案 |
|---|---|
| 100GB内存溢出 | 采用流式分片处理,禁用内存完整缓存 |
| FastDFS国密扩展失败 | 预留本地加密后上传的回退方案 |
| IE8插件限制 | 与浏览器厂商联合调试,采用ActiveX控件(仅限内网) |
| 信创硬件兼容性问题 | 提前在长城/飞腾服务器上测试,准备驱动兼容层 |
该方案已在统信UOS+鲲鹏920环境下验证,实现50GB文件稳定传输(速度8MB/s),SM4加密对性能影响控制在20%以内。下一步将优化WebAssembly加密性能,目标提升至15MB/s。
支持离线保存文件进度,在关闭浏览器,刷新浏览器后进行不丢失,仍然能够继续上传
支持上传文件夹并保留层级结构,同样支持进度信息离线保存,刷新页面,关闭页面,重启系统不丢失上传进度。
支持文件批量下载
文件下载支持离线保存进度信息,刷新页面,关闭页面,重启系统均不会丢失进度信息。
支持下载文件夹,并保留层级结构,不打包,不占用服务器资源。
下载完整示例