const COS = require('cos-nodejs-sdk-v5'); const {dialog} = require('electron') const {readFileSync} = require('node:fs') const md5 = require("md5"); class UploadUtils { static cos = new COS({ SecretId: 'AKIDvjKhqrfEaliRq11nMcrGZmsATiyNl1BA', // 推荐使用环境变量获取;用户的 SecretId,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。 // 子账号密钥获取可参考https://cloud.tencent.com/document/product/598/37140 SecretKey: 'xpZCjCTVJzZG2wyy8mFVwLWTVVIqAKct', Domain: 'https://note-1324909903.cos.ap-beijing.myqcloud.com' }); static Bucket = 'note-1324909903' static Region = 'ap-beijing' static staticStore constructor(store) { this.store = store; UploadUtils.staticStore = store; } getActiveFile() { let tableBarItem = JSON.parse(this.store.get("persist:tableBarItem")); if (!tableBarItem) { return; } return tableBarItem.activeKey ? JSON.parse(tableBarItem.activeKey) : undefined; } /* * 检测本地和远程文件是否相同 */ getLocalFileMd5(activeFile) { let dirMessage = JSON.parse(this.store.get("persist:dirMessage")); let fileMd5 if (activeFile && dirMessage && dirMessage.data) { let find = JSON.parse(dirMessage.data, []).find(file => file.fileId === activeFile || file.filePath === activeFile); if (find) { fileMd5 = find.fileMd5; } } if (!fileMd5) { fileMd5 = md5(readFileSync(activeFile).toString()) } return fileMd5 } upLoadFileUtil(activeFile) { // 判断文件是否相同 let fileMd5 = this.getLocalFileMd5(activeFile); UploadUtils.cos.headObject({ Bucket: UploadUtils.Bucket, Region: UploadUtils.Region, // 不能以 / 开头 Key: process.platform==='win32'?activeFile.replaceAll("\\","/"):activeFile }, function (err, data) { console.log('upLoadFileUtil:',err || data); if (data && data.ETag) { // 文件存在,比较MD5值 let onlineMd5 = data.ETag.replaceAll('"', "") if (onlineMd5 === fileMd5) { dialog.showMessageBoxSync({ "message": "云文件和本地相同无需同步", "type": "info", "buttons": ["确认"], "defaultId": 0 }); return } } UploadUtils.selfUploadFile(activeFile,fileMd5) }) } downLoadFileUtil(activeFile) { // 判断文件是否相同 let fileMd5 = this.getLocalFileMd5(activeFile); UploadUtils.cos.headObject({ Bucket: UploadUtils.Bucket, Region: UploadUtils.Region, // 不能以 / 开头 Key: process.platform==='win32'?activeFile.replaceAll("\\","/"):activeFile, }, function (err, data) { console.log('downLoadFileUtil:',err || data); if (data && data.ETag) { // 文件存在,比较MD5值 let onlineMd5 = data.ETag.replaceAll('"', "") if (onlineMd5 === fileMd5) { dialog.showMessageBoxSync({ "message": "云文件和本地相同无需同步", "type": "info", "buttons": ["确认"], "defaultId": 0 }); return } } UploadUtils.selfDownLoadFile(activeFile) }) } static selfUploadFile(activeFile,fileMd5) { console.log("cos.uploadFile",activeFile,fileMd5) UploadUtils.cos.uploadFile({ Bucket: UploadUtils.Bucket, /* 填入您自己的存储桶,必须字段 */ Region: UploadUtils.Region, /* 存储桶所在地域,例如 ap-beijing,必须字段 */ Key: process.platform==='win32'?activeFile.replaceAll("\\","/"):activeFile, /* 存储在桶里的对象键(例如1.jpg,a/b/test.txt),必须字段 */ FilePath: activeFile, /* 必须 */ SliceSize: 1024 * 1024 * 5, /* 触发分块上传的阈值,超过5MB使用分块上传,非必须 */ onTaskReady: function (taskId) { /* 非必须 */ console.log(taskId); }, onProgress: function (progressData) { /* 非必须 */ console.log(JSON.stringify(progressData)); }, onFileFinish: function (err, data, options) { /* 非必须 */ console.log(options.Key + '上传' + (err ? '失败' : '完成')); if (err){ dialog.showMessageBoxSync({ "message": err, "type": "error", "buttons": ["确认"], "defaultId": 0 }) }else { dialog.showMessageBoxSync({ "message": "同步完成", "type": "info", "buttons": ["确认"], "defaultId": 0 }) } }, // 支持自定义headers 非必须 }, function (err, data) { console.log("uploadFile:callback:",err || data); }); } static selfDownLoadFile(activeFile) { console.log("cos.downloadFile", activeFile) UploadUtils.cos.getObject({ Bucket: UploadUtils.Bucket, /* 填入您自己的存储桶,必须字段 */ Region: UploadUtils.Region, /* 存储桶所在地域,例如 ap-beijing,必须字段 */ Key: process.platform==='win32'?activeFile.replaceAll("\\","/"):activeFile, /* 存储在桶里的对象键(例如1.jpg,a/b/test.txt),必须字段 */ Output: activeFile // 支持自定义headers 非必须 }, function (err, data) { console.log(err || data); if (err){ dialog.showMessageBoxSync({ "message": err, "type": "error", "buttons": ["确认"], "defaultId": 0 }) }else { dialog.showMessageBoxSync({ "message": "同步完成", "type": "info", "buttons": ["确认"], "defaultId": 0 }) // 修改store中Md5值 let persist = UploadUtils.staticStore.get("persist:dirMessage"); if (persist){ let persistObj = JSON.parse(persist) let data1 = persistObj.data; console.log("data1",data1,Array.isArray(data1)) let parseArray = JSON.parse(data1, []); let find =parseArray.find(file => file.fileId === activeFile || file.filePath === activeFile); if (find) { find.fileMd5=data.ETag.replaceAll('"',""); } persistObj.data=JSON.stringify(parseArray) UploadUtils.staticStore.set("persist:dirMessage",JSON.stringify(persistObj)) } } }); } syncActiveFile() { let activeFile = this.getActiveFile(); console.log("activeFile:", activeFile) if (activeFile) { let fileMd5 = this.getLocalFileMd5(activeFile); UploadUtils.cos.headObject({ Bucket: UploadUtils.Bucket, Region: UploadUtils.Region, // 不能以 / 开头 Key: process.platform==='win32'?activeFile.replaceAll("\\","/"):activeFile, }, function (err, data) { console.log("err || data.CommonPrefixes" + activeFile, err || data); if (data && data.ETag) { // 文件存在,比较MD5值 let onlineMd5 = data.ETag.replaceAll('"', "") if (onlineMd5 === fileMd5) { return } console.log("fileList[0].ETag", onlineMd5) dialog.showMessageBox({ "message": "云文件已修改是否同步到本地", "type": "info", "buttons": ["是", "否"], "defaultId": 0 }).then(result=>{ let number = result.response if (number === 0) { UploadUtils.selfDownLoadFile(activeFile) } else if (number === 1) { dialog.showMessageBox({ "message": "是否使用本地文件覆盖远程文件", "type": "info", "buttons": ["是", "否"], "defaultId": 0 }).then(result=>{ if (result.response===0){ UploadUtils.selfUploadFile(activeFile,fileMd5) } }) } }); } else { UploadUtils.selfUploadFile(activeFile,fileMd5) } }); } } syncFile() { console.log("同步数据") // 1. 先同步active文件数据 this.syncActiveFile() // 2. 同步bar中数据 // 3. 同步树中的数据。 } } module.exports = UploadUtils