diff --git a/src/main/index.js b/src/main/index.js index 898e561c..b4f7e492 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -59,6 +59,15 @@ function createTray () { db.read().set('picBed.current', 'qiniu') .write() } + }, + { + label: '腾讯云COS', + type: 'radio', + checked: db.read().get('picBed.current').value() === 'tcyun', + click () { + db.read().set('picBed.current', 'tcyun') + .write() + } } ] }, diff --git a/src/main/utils/tcYunUpload.js b/src/main/utils/tcYunUpload.js new file mode 100644 index 00000000..f346197b --- /dev/null +++ b/src/main/utils/tcYunUpload.js @@ -0,0 +1,90 @@ +import request from 'request-promise' +import * as img2Base64 from './img2base64' +import db from '../../datastore/index' +import { Notification, clipboard } from 'electron' +import crypto from 'crypto' + +// generate COS signature string +const generateSignature = () => { + const options = db.read().get('picBed.tcyun').value() + const secretId = options.secretId + const secretKey = options.secretKey + const appId = options.appId + const bucket = options.bucket + const random = Math.floor(Math.random() * 10000000000) + const current = parseInt(new Date().getTime() / 1000) - 1 + const expired = current + 3600 + + const multiSignature = `a=${appId}&b=${bucket}&k=${secretId}&e=${expired}&t=${current}&r=${random}&f=` + + const signHexKey = crypto.createHmac('sha1', secretKey).update(multiSignature).digest() + const tempString = Buffer.concat([signHexKey, Buffer.from(multiSignature)]) + const signature = Buffer.from(tempString).toString('base64') + return { + signature, + appId, + bucket + } +} + +const postOptions = (fileName, signature, imgBase64) => { + const area = db.read().get('picBed.tcyun.area').value() + const path = db.read().get('picBed.tcyun.path').value() + return { + method: 'POST', + url: `http://${area}.file.myqcloud.com/files/v2/${signature.appId}/${signature.bucket}/${path}${fileName}`, + headers: { + Host: `${area}.file.myqcloud.com`, + Authorization: signature.signature, + contentType: 'multipart/form-data' + }, + formData: { + op: 'upload', + filecontent: Buffer.from(imgBase64, 'base64') + } + } +} + +const tcYunUpload = async (img, type, webContents) => { + try { + webContents.send('uploadProgress', 0) + const imgList = await img2Base64[type](img) + webContents.send('uploadProgress', 30) + const singature = generateSignature() + const length = imgList.length + for (let i in imgList) { + const options = postOptions(imgList[i].fileName, singature, imgList[i].base64Image) + const res = await request(options) + const body = JSON.parse(res) + if (body.message === 'SUCCESS') { + delete imgList[i].base64Image + imgList[i]['imgUrl'] = body.data.source_url + imgList[i]['type'] = 'tcyun' + if (i - length === -1) { + webContents.send('uploadProgress', 60) + } + } else { + webContents.send('uploadProgress', -1) + const notification = new Notification({ + title: '上传失败!', + body: res.body.msg + }) + notification.show() + } + } + webContents.send('uploadProgress', 100) + return imgList + } catch (err) { + const body = JSON.parse(err.error) + webContents.send('uploadProgress', -1) + const notification = new Notification({ + title: '上传失败!', + body: `错误码:${body.code},请打开浏览器粘贴地址查看相关原因。` + }) + notification.show() + clipboard.writeText('https://cloud.tencent.com/document/product/436/8432') + throw new Error(err) + } +} + +export default tcYunUpload diff --git a/src/main/utils/uploader.js b/src/main/utils/uploader.js index 567ff84f..ba33d9c5 100644 --- a/src/main/utils/uploader.js +++ b/src/main/utils/uploader.js @@ -1,5 +1,6 @@ import weiboUpload from './weiboUpload' import qiniuUpload from './qiniuUpload' +import tcYunUpload from './tcYunUpload' import db from '../../datastore/index' const uploader = (img, type, webContents) => { const uploadType = db.read().get('picBed.current').value() @@ -8,6 +9,8 @@ const uploader = (img, type, webContents) => { return weiboUpload(img, type, webContents) case 'qiniu': return qiniuUpload(img, type, webContents) + case 'tcyun': + return tcYunUpload(img, type, webContents) } } diff --git a/src/main/utils/weiboUpload.js b/src/main/utils/weiboUpload.js index b09afb41..3999d6c4 100644 --- a/src/main/utils/weiboUpload.js +++ b/src/main/utils/weiboUpload.js @@ -6,7 +6,7 @@ const j = request.jar() const rp = request.defaults({jar: j}) const UPLOAD_URL = 'http://picupload.service.weibo.com/interface/pic_upload.php?ori=1&mime=image%2Fjpeg&data=base64&url=0&markpos=1&logo=&nick=0&marks=1&app=miniblog' -function postOptions (formData) { +const postOptions = (formData) => { return { method: 'POST', url: 'https://passport.weibo.cn/sso/login', diff --git a/src/renderer/assets/fonts/iconfont.css b/src/renderer/assets/fonts/iconfont.css index ca8fca2b..b8512ecf 100644 --- a/src/renderer/assets/fonts/iconfont.css +++ b/src/renderer/assets/fonts/iconfont.css @@ -1,10 +1,10 @@ @font-face {font-family: "iconfont"; - src: url('iconfont.eot?t=1512627299425'); /* IE9*/ - src: url('iconfont.eot?t=1512627299425#iefix') format('embedded-opentype'), /* IE6-IE8 */ - url('data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAAccAAsAAAAACgAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADMAAABCsP6z7U9TLzIAAAE8AAAARAAAAFZW7kgJY21hcAAAAYAAAABtAAABqjJq0p5nbHlmAAAB8AAAAyIAAAOsU27YCmhlYWQAAAUUAAAALwAAADYPvT7DaGhlYQAABUQAAAAcAAAAJAfeA4ZobXR4AAAFYAAAABMAAAAUE+kAAGxvY2EAAAV0AAAADAAAAAwB+gL0bWF4cAAABYAAAAAfAAAAIAEVAHluYW1lAAAFoAAAAUUAAAJtPlT+fXBvc3QAAAboAAAAMwAAAETD3CS1eJxjYGRgYOBikGPQYWB0cfMJYeBgYGGAAJAMY05meiJQDMoDyrGAaQ4gZoOIAgCKIwNPAHicY2Bk/s04gYGVgYOpk+kMAwNDP4RmfM1gxMjBwMDEwMrMgBUEpLmmMDgwVDyTYW7438AQw9zA0AAUZgTJAQAmaQyLeJzFkdENgCAMRK+Chhg3gBEcwE+H8csJmLhr4FH64wQceXC9lEAAwAogkJNEQF4Iuh6mYnnAbnnExTpxLFyripbW3GVzXWIdyVzkXvbKhmmSeUf/ddh8e8WXRnV4RXV6rnnQf0XLAMsHNt4SBQAAAHicTVLNixxFFK9X1VU9M91dPd3TUz0f2/O5272ym57dnd7uxI09ugkJmsAoS+IOOWzChkAgehA2e0nIgIgfRIyXRT2tokhELznoJScRvMx/4MH4cQ0hggERR6tXFlI8fnT96r2uer/3QxShf38h90kFldA8WkYn0csIAVuADscetIMoxAtQbtOy63ASdIO22u2E5DlwO8wRK3Hku0xlJnBoQL+9EgchDmA1SvEarAgPoFqvbdhzMza5A4VK0Hhr+hL+DMrN7oyZHpm+uDhwVlql3K5u21Xbvp1jlOYwVkwOr7kiT/MFNv2cmrXy/eYzuAl6NaidHRmtun3pneh1b87NA4zHUKq3+JcDq2bJuFETJbuqFo1cpWZ0Zx3Y/V2rlHTP/w3JxWSvP5InZIQECtEZ9CraRtdktw7r+EHSDSFQV0OI4oFsxl1WO/5qlEiSdTMy6Wdk2WFq7DZA5QchT5PYTmKhMjUFyVNJyrwUZCGRp/JDbjkEh3KRP7ngAIDfvZLL63o+d+MLsqdxrAx6CtW4JE5vYXO34UchIVc3n/1w+PXfDNx/Th/dxEAWL4aD9vTjW3cV5e6tcYb7J0YYj06sZ3hOeN6i5+G2Zpqacu0DIq/hZY5B+ebNhqkxurxOMJiCY3z5jKKZp5Q8PxWv7R+d7wH5alx8G2qW2lsv6PWZHN8e4uubox2Md0ab16cfwUaabsAB7jePNGUgpEg998kDchHpqIJmUYrQnOy2n0LkSwMxEMiNUeKjgCH3UAmpWcKkUmtQdoR0SZys9iXEPfA7KvwAReO4YVnGcd2aXqBgTiZgUjp9PJlMHyf04b17D+kBPuEEF7ULB4kw0oqY8Nt6S39D7sCqWhJlAX36B4eVEv+whMb3smv2uCasTw0DQWYQ8gh/i5akI2KmCqZ2AjlBN8xm2ciGKyMRcZJCEPn/GyBLEP3ZmPxUqij457+GL/B5j453AAvj5nvM0p3hxvktw3AgJ1pJgW8vOHUu/YUmeKcHCv+em0vPs614TBXz7Hfrr9xpHGtg7C0d+8RQC3bnfcuwDPvmUNN/la/7DxamqC0AAHicY2BkYGAA4oe6X1vi+W2+MnCzMIDANb+/yQj6/wIWBuYEIJeDgQkkCgBOHQtQAHicY2BkYGBu+N/AEMPCAAJAkpEBFbACAEcLAm54nGNhYGBgfsnAwMKAwAAOmwD9AAAAAAAAdgEeAYQB1nicY2BkYGBgZchlYGMAASYg5gJCBob/YD4DABQAAY8AeJxlj01OwzAQhV/6B6QSqqhgh+QFYgEo/RGrblhUavdddN+mTpsqiSPHrdQDcB6OwAk4AtyAO/BIJ5s2lsffvHljTwDc4Acejt8t95E9XDI7cg0XuBeuU38QbpBfhJto41W4Rf1N2MczpsJtdGF5g9e4YvaEd2EPHXwI13CNT+E69S/hBvlbuIk7/Aq30PHqwj7mXle4jUcv9sdWL5xeqeVBxaHJIpM5v4KZXu+Sha3S6pxrW8QmU4OgX0lTnWlb3VPs10PnIhVZk6oJqzpJjMqt2erQBRvn8lGvF4kehCblWGP+tsYCjnEFhSUOjDFCGGSIyujoO1Vm9K+xQ8Jee1Y9zed0WxTU/3OFAQL0z1xTurLSeTpPgT1fG1J1dCtuy56UNJFezUkSskJe1rZUQuoBNmVXjhF6XNGJPyhnSP8ACVpuyAAAAHicY2BigAAuBuyAlZGJkZmRhZGVkY2BsYK1PDUzKZ+ttCAnPzGFtTAzL7OUgQEAX20HdQA=') format('woff'), - url('iconfont.ttf?t=1512627299425') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ - url('iconfont.svg?t=1512627299425#iconfont') format('svg'); /* iOS 4.1- */ + src: url('iconfont.eot?t=1513753554908'); /* IE9*/ + src: url('iconfont.eot?t=1513753554908#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'), + url('iconfont.ttf?t=1513753554908') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ + url('iconfont.svg?t=1513753554908#iconfont') format('svg'); /* iOS 4.1- */ } [class*=" el-icon-ui"], [class^=el-icon-ui] { @@ -17,7 +17,11 @@ .el-icon-ui-weibo:before { content: "\e61c"; } +.el-icon-ui-tcyun:before { content: "\e64c"; } + .el-icon-ui-upload:before { content: "\e61b"; } .el-icon-ui-qiniu:before { content: "\e601"; } +.el-icon-ui-upyun:before { content: "\e602"; } + diff --git a/src/renderer/assets/fonts/iconfont.eot b/src/renderer/assets/fonts/iconfont.eot index 2e61730d..1523bca3 100644 Binary files a/src/renderer/assets/fonts/iconfont.eot and b/src/renderer/assets/fonts/iconfont.eot differ diff --git a/src/renderer/assets/fonts/iconfont.svg b/src/renderer/assets/fonts/iconfont.svg index a7afe8fc..ca5c855c 100644 --- a/src/renderer/assets/fonts/iconfont.svg +++ b/src/renderer/assets/fonts/iconfont.svg @@ -30,12 +30,18 @@ t9.5 -10.5t21.5 -4h37h67h81h80h64h36q23 0 34 12t2 38q-5 13 -9.5 30.5t-9.5 34.5q- + + + + + + diff --git a/src/renderer/assets/fonts/iconfont.ttf b/src/renderer/assets/fonts/iconfont.ttf index 0276b8f4..efa9c777 100644 Binary files a/src/renderer/assets/fonts/iconfont.ttf and b/src/renderer/assets/fonts/iconfont.ttf differ diff --git a/src/renderer/assets/fonts/iconfont.woff b/src/renderer/assets/fonts/iconfont.woff index dbb1dab2..d01359e2 100644 Binary files a/src/renderer/assets/fonts/iconfont.woff and b/src/renderer/assets/fonts/iconfont.woff differ diff --git a/src/renderer/components/SettingPage.vue b/src/renderer/components/SettingPage.vue index 7a2b1110..be61b3fd 100644 --- a/src/renderer/components/SettingPage.vue +++ b/src/renderer/components/SettingPage.vue @@ -26,6 +26,10 @@ 七牛设置 + + + 腾讯COS设置 + diff --git a/src/renderer/components/SettingView/TcYun.vue b/src/renderer/components/SettingView/TcYun.vue new file mode 100644 index 00000000..0dd1518c --- /dev/null +++ b/src/renderer/components/SettingView/TcYun.vue @@ -0,0 +1,142 @@ + + + \ No newline at end of file diff --git a/src/renderer/router/index.js b/src/renderer/router/index.js index 286aa2a9..e88b6526 100644 --- a/src/renderer/router/index.js +++ b/src/renderer/router/index.js @@ -30,6 +30,11 @@ export default new Router({ component: require('@/components/SettingView/Qiniu').default, name: 'qiniu' }, + { + path: 'tcyun', + component: require('@/components/SettingView/TcYun').default, + name: 'tcyun' + }, { path: 'gallery', component: require('@/components/SettingView/Gallery').default,