diff --git a/package.json b/package.json
index 5a52c0a0..7325400e 100644
--- a/package.json
+++ b/package.json
@@ -71,6 +71,7 @@
"image-size": "^0.6.1",
"lodash-id": "^0.14.0",
"lowdb": "^1.0.0",
+ "md5": "^2.2.1",
"melody.css": "^1.0.2",
"qiniu": "^7.1.1",
"request": "^2.83.0",
diff --git a/src/main/index.js b/src/main/index.js
index b4f7e492..482e768d 100644
--- a/src/main/index.js
+++ b/src/main/index.js
@@ -23,6 +23,14 @@ const settingWinURL = process.env.NODE_ENV === 'development'
? `http://localhost:9080/#setting/upload`
: `file://${__dirname}/index.html#setting/upload`
+const uploadFailed = () => {
+ const notification = new Notification({
+ title: '上传失败',
+ body: '请检查你的图床配置!'
+ })
+ notification.show()
+}
+
function createTray () {
tray = new Tray(`${__static}/menubar.png`)
const contextMenu = Menu.buildFromTemplate([
@@ -68,6 +76,15 @@ function createTray () {
db.read().set('picBed.current', 'tcyun')
.write()
}
+ },
+ {
+ label: '又拍云图床',
+ type: 'radio',
+ checked: db.read().get('picBed.current').value() === 'upyun',
+ click () {
+ db.read().set('picBed.current', 'upyun')
+ .write()
+ }
}
]
},
@@ -109,18 +126,22 @@ function createTray () {
tray.on('drop-files', async (event, files) => {
const pasteStyle = db.read().get('picBed.pasteStyle').value() || 'markdown'
const imgs = await uploader(files, 'imgFromPath', window.webContents)
- for (let i in imgs) {
- clipboard.writeText(pasteTemplate(pasteStyle, imgs[i].imgUrl))
- const notification = new Notification({
- title: '上传成功',
- body: imgs[i].imgUrl,
- icon: files[i]
- })
- setTimeout(() => {
- notification.show()
- }, i * 100)
+ if (imgs !== false) {
+ for (let i in imgs) {
+ clipboard.writeText(pasteTemplate(pasteStyle, imgs[i].imgUrl))
+ const notification = new Notification({
+ title: '上传成功',
+ body: imgs[i].imgUrl,
+ icon: files[i]
+ })
+ setTimeout(() => {
+ notification.show()
+ }, i * 100)
+ }
+ window.webContents.send('dragFiles', imgs)
+ } else {
+ uploadFailed()
}
- window.webContents.send('dragFiles', imgs)
})
// toggleWindow()
}
@@ -232,35 +253,43 @@ const showWindow = () => {
ipcMain.on('uploadClipboardFiles', async (evt, file) => {
const img = await uploader(file, 'imgFromClipboard', window.webContents)
- const pasteStyle = db.read().get('picBed.pasteStyle').value() || 'markdown'
- clipboard.writeText(pasteTemplate(pasteStyle, img[0].imgUrl))
- const notification = new Notification({
- title: '上传成功',
- body: img[0].imgUrl,
- icon: file[0]
- })
- notification.show()
- window.webContents.send('clipboardFiles', [])
- window.webContents.send('uploadFiles', img)
+ if (img !== false) {
+ const pasteStyle = db.read().get('picBed.pasteStyle').value() || 'markdown'
+ clipboard.writeText(pasteTemplate(pasteStyle, img[0].imgUrl))
+ const notification = new Notification({
+ title: '上传成功',
+ body: img[0].imgUrl,
+ icon: file[0]
+ })
+ notification.show()
+ window.webContents.send('clipboardFiles', [])
+ window.webContents.send('uploadFiles', img)
+ } else {
+ uploadFailed()
+ }
})
ipcMain.on('uploadChoosedFiles', async (evt, files) => {
const imgs = await uploader(files, 'imgFromUploader', settingWindow.webContents)
- const pasteStyle = db.read().get('picBed.pasteStyle').value() || 'markdown'
- let pasteText = ''
- for (let i in imgs) {
- pasteText += pasteTemplate(pasteStyle, imgs[i].imgUrl) + '\r\n'
- const notification = new Notification({
- title: '上传成功',
- body: imgs[i].imgUrl,
- icon: files[i].path
- })
- setTimeout(() => {
- notification.show()
- }, i * 100)
+ if (imgs !== false) {
+ const pasteStyle = db.read().get('picBed.pasteStyle').value() || 'markdown'
+ let pasteText = ''
+ for (let i in imgs) {
+ pasteText += pasteTemplate(pasteStyle, imgs[i].imgUrl) + '\r\n'
+ const notification = new Notification({
+ title: '上传成功',
+ body: imgs[i].imgUrl,
+ icon: files[i].path
+ })
+ setTimeout(() => {
+ notification.show()
+ }, i * 100)
+ }
+ clipboard.writeText(pasteText)
+ window.webContents.send('uploadFiles', imgs)
+ } else {
+ uploadFailed()
}
- clipboard.writeText(pasteText)
- window.webContents.send('uploadFiles', imgs)
})
app.on('ready', () => {
diff --git a/src/main/utils/upYunUpload.js b/src/main/utils/upYunUpload.js
new file mode 100644
index 00000000..9dc76dce
--- /dev/null
+++ b/src/main/utils/upYunUpload.js
@@ -0,0 +1,80 @@
+import request from 'request-promise'
+import * as img2Base64 from './img2base64'
+import db from '../../datastore/index'
+import { Notification, clipboard } from 'electron'
+import crypto from 'crypto'
+import MD5 from 'md5'
+
+// generate COS signature string
+const generateSignature = (fileName) => {
+ const options = db.read().get('picBed.upyun').value()
+ // const apiKey = options.apiKey
+ const operator = options.operator
+ const password = options.password
+ const md5Password = MD5(password)
+ const date = new Date().toGMTString()
+ const uri = `/${options.bucket}/${fileName}`
+ const value = `PUT&${uri}&${date}`
+ const sign = crypto.createHmac('sha1', md5Password).update(value).digest('base64')
+ return `UPYUN ${operator}:${sign}`
+}
+
+const postOptions = (fileName, signature, imgBase64) => {
+ const options = db.read().get('picBed.upyun').value()
+ const bucket = options.bucket
+ return {
+ method: 'PUT',
+ url: `https://v0.api.upyun.com/${bucket}/${fileName}`,
+ headers: {
+ Authorization: signature,
+ Date: new Date().toGMTString()
+ },
+ body: Buffer.from(imgBase64, 'base64'),
+ resolveWithFullResponse: true
+ }
+}
+
+const upYunUpload = async (img, type, webContents) => {
+ try {
+ webContents.send('uploadProgress', 0)
+ const imgList = await img2Base64[type](img)
+ webContents.send('uploadProgress', 30)
+ const length = imgList.length
+ const upyunOptions = db.read().get('picBed.upyun').value()
+ for (let i in imgList) {
+ const singature = generateSignature(imgList[i].fileName)
+ const options = postOptions(imgList[i].fileName, singature, imgList[i].base64Image)
+ const body = await request(options)
+ if (body.statusCode === 200) {
+ delete imgList[i].base64Image
+ imgList[i]['imgUrl'] = `${upyunOptions.url}/${imgList[i].fileName}${upyunOptions.options}`
+ imgList[i]['type'] = 'upyun'
+ if (i - length === -1) {
+ webContents.send('uploadProgress', 60)
+ }
+ } else {
+ webContents.send('uploadProgress', -1)
+ const notification = new Notification({
+ title: '上传失败!',
+ body: '服务端出错,请稍后再试'
+ })
+ notification.show()
+ }
+ }
+ webContents.send('uploadProgress', 100)
+ return imgList
+ } catch (err) {
+ console.log(err)
+ const body = JSON.parse(err.error)
+ webContents.send('uploadProgress', -1)
+ const notification = new Notification({
+ title: '上传失败!',
+ body: `错误码:${body.code},请打开浏览器粘贴地址查看相关原因。`
+ })
+ notification.show()
+ clipboard.writeText('http://docs.upyun.com/api/errno/')
+ // throw new Error(err)
+ }
+}
+
+export default upYunUpload
diff --git a/src/main/utils/uploader.js b/src/main/utils/uploader.js
index ba33d9c5..1a26fa01 100644
--- a/src/main/utils/uploader.js
+++ b/src/main/utils/uploader.js
@@ -1,16 +1,33 @@
import weiboUpload from './weiboUpload'
import qiniuUpload from './qiniuUpload'
import tcYunUpload from './tcYunUpload'
+import upYunUpload from './upYunUpload'
import db from '../../datastore/index'
+
+const checkUploader = (type) => {
+ const currentUploader = db.read().get(`picBed.${type}`).value()
+ if (currentUploader) {
+ return true
+ } else {
+ return false
+ }
+}
+
const uploader = (img, type, webContents) => {
const uploadType = db.read().get('picBed.current').value()
- switch (uploadType) {
- case 'weibo':
- return weiboUpload(img, type, webContents)
- case 'qiniu':
- return qiniuUpload(img, type, webContents)
- case 'tcyun':
- return tcYunUpload(img, type, webContents)
+ if (checkUploader(uploadType)) {
+ switch (uploadType) {
+ case 'weibo':
+ return weiboUpload(img, type, webContents)
+ case 'qiniu':
+ return qiniuUpload(img, type, webContents)
+ case 'tcyun':
+ return tcYunUpload(img, type, webContents)
+ case 'upyun':
+ return upYunUpload(img, type, webContents)
+ }
+ } else {
+ return false
}
}
diff --git a/src/renderer/components/SettingPage.vue b/src/renderer/components/SettingPage.vue
index be61b3fd..8c5baabc 100644
--- a/src/renderer/components/SettingPage.vue
+++ b/src/renderer/components/SettingPage.vue
@@ -24,12 +24,16 @@
- 七牛设置
+ 七牛云设置
腾讯COS设置
+
+
+ 又拍云设置
+
diff --git a/src/renderer/components/SettingView/Qiniu.vue b/src/renderer/components/SettingView/Qiniu.vue
index e95d4026..cca0348d 100644
--- a/src/renderer/components/SettingView/Qiniu.vue
+++ b/src/renderer/components/SettingView/Qiniu.vue
@@ -36,7 +36,7 @@
+
+
+
+ 又拍云设置
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 确定
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/renderer/router/index.js b/src/renderer/router/index.js
index e88b6526..90fac1ba 100644
--- a/src/renderer/router/index.js
+++ b/src/renderer/router/index.js
@@ -35,6 +35,11 @@ export default new Router({
component: require('@/components/SettingView/TcYun').default,
name: 'tcyun'
},
+ {
+ path: 'upyun',
+ component: require('@/components/SettingView/UpYun').default,
+ name: 'upyun'
+ },
{
path: 'gallery',
component: require('@/components/SettingView/Gallery').default,
diff --git a/yarn.lock b/yarn.lock
index 46895b47..19fa97bf 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1861,6 +1861,10 @@ chardet@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.0.tgz#0bbe1355ac44d7a3ed4a925707c4ef70f8190f6c"
+charenc@~0.0.1:
+ version "0.0.2"
+ resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
+
check-error@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
@@ -2303,6 +2307,10 @@ cross-unzip@0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/cross-unzip/-/cross-unzip-0.0.2.tgz#5183bc47a09559befcf98cc4657964999359372f"
+crypt@~0.0.1:
+ version "0.0.2"
+ resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
+
cryptiles@2.x.x:
version "2.0.5"
resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
@@ -4392,7 +4400,7 @@ is-binary-path@^1.0.0:
dependencies:
binary-extensions "^1.0.0"
-is-buffer@^1.0.2, is-buffer@^1.1.5:
+is-buffer@^1.0.2, is-buffer@^1.1.5, is-buffer@~1.1.1:
version "1.1.6"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
@@ -5269,6 +5277,14 @@ md5.js@^1.3.4:
hash-base "^3.0.0"
inherits "^2.0.1"
+md5@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9"
+ dependencies:
+ charenc "~0.0.1"
+ crypt "~0.0.1"
+ is-buffer "~1.1.1"
+
media-typer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"