mirror of
https://github.com/doocs/md.git
synced 2024-11-24 19:10:34 +08:00
feat: support qiniu kodo
This commit is contained in:
parent
5ae6fd4b28
commit
3fac278a83
@ -49,6 +49,7 @@ Markdown 文档自动即时渲染为微信图文,让你不再为微信文章
|
||||
| 2 | GitHub 图床 | 配置 `Repo`、`Token` 参数 | [如何获取 GitHub token?](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) |
|
||||
| 3 | 阿里云 OSS | 配置 `AccessKey ID`、`AccessKey Secret`、`Bucket`、`Region` 等参数 | [如何使用阿里云 OSS?](https://help.aliyun.com/document_detail/31883.html) |
|
||||
| 4 | 腾讯云 COS | 配置 `SecretId`、`SecretKey`、`Bucket`、`Region` 等参数 | [如何使用腾讯云 COS?](https://cloud.tencent.com/document/product/436/38484) |
|
||||
| 5 | 七牛云 Kodo | 配置 `AccessKey`、`SecretKey`、`Bucket`、`Domain`、`Region` 等参数 | [如何使用七牛云 Kodo?](https://cloud.tencent.com/document/product/436/38484) |
|
||||
|
||||
![select-and-change-color-theme](./public/assets/images/select-and-change-color-theme.gif)
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "vue-md",
|
||||
"author": "doocs",
|
||||
"version": "1.4.1",
|
||||
"version": "1.4.2",
|
||||
"private": true,
|
||||
"homepage": "https://doocs.gitee.io/md",
|
||||
"scripts": {
|
||||
@ -17,12 +17,14 @@
|
||||
"codemirror": "^5.50.2",
|
||||
"core-js": "^3.4.4",
|
||||
"cos-js-sdk-v5": "^0.5.27",
|
||||
"crypto-js": "^4.0.0",
|
||||
"element-ui": "^2.13.0",
|
||||
"jquery": "^3.4.1",
|
||||
"juice": "^6.0.0",
|
||||
"marked": "^0.8.0",
|
||||
"prettier": "^2.0.5",
|
||||
"prettify": "^0.1.7",
|
||||
"qiniu-js": "^3.1.2",
|
||||
"uuid": "^8.3.0",
|
||||
"vue": "^2.6.10",
|
||||
"vue-router": "^3.1.3",
|
||||
|
@ -1,8 +1,11 @@
|
||||
import fetch from "./fetch";
|
||||
import CryptoJS from "crypto-js";
|
||||
import OSS from "ali-oss";
|
||||
import COS from "cos-js-sdk-v5";
|
||||
import Buffer from "buffer-from";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import * as qiniu from "qiniu-js";
|
||||
import { utf16to8, base64encode, safe64 } from "../assets/scripts/tokenTools";
|
||||
|
||||
const defaultConfig = {
|
||||
username: "filess",
|
||||
@ -28,6 +31,8 @@ function fileUpload(content, file) {
|
||||
return aliOSSFileUpload(content, file.name);
|
||||
case "txCOS":
|
||||
return txCOSFileUpload(file);
|
||||
case "qiniu":
|
||||
return qiniuUpload(file);
|
||||
case "github":
|
||||
default:
|
||||
return ghFileUpload(content, file.name);
|
||||
@ -81,6 +86,14 @@ function getGitHubConfig() {
|
||||
);
|
||||
}
|
||||
|
||||
function getQiniuToken(accessKey, secretKey, putPolicy) {
|
||||
const policy = JSON.stringify(putPolicy);
|
||||
const encoded = base64encode(utf16to8(policy));
|
||||
const hash = CryptoJS.HmacSHA1(encoded, secretKey);
|
||||
const encodedSigned = hash.toString(CryptoJS.enc.Base64);
|
||||
return accessKey + ":" + safe64(encodedSigned) + ":" + encoded;
|
||||
}
|
||||
|
||||
async function ghFileUpload(content, filename) {
|
||||
const isDefault = localStorage.getItem("imgHost") !== "github";
|
||||
const config = isDefault ? getDefaultConfig() : getGitHubConfig();
|
||||
@ -166,6 +179,44 @@ async function txCOSFileUpload(file) {
|
||||
});
|
||||
}
|
||||
|
||||
async function qiniuUpload(file) {
|
||||
const qiniuConfig = JSON.parse(localStorage.getItem("qiniuConfig"));
|
||||
const putPolicy = {
|
||||
scope: qiniuConfig.bucket,
|
||||
deadline: Math.trunc(new Date().getTime() / 1000) + 3600,
|
||||
};
|
||||
const token = getQiniuToken(
|
||||
qiniuConfig.accessKey,
|
||||
qiniuConfig.secretKey,
|
||||
putPolicy
|
||||
);
|
||||
const dir = qiniuConfig.path ? qiniuConfig.path + "/" : "";
|
||||
const dateFilename =
|
||||
dir +
|
||||
new Date().getTime() +
|
||||
"-" +
|
||||
uuidv4() +
|
||||
"." +
|
||||
file.name.split(".")[1];
|
||||
const config = {
|
||||
region: qiniuConfig.region,
|
||||
};
|
||||
const observable = qiniu.upload(file, dateFilename, token, {}, config);
|
||||
return new Promise((resolve, reject) => {
|
||||
observable.subscribe({
|
||||
next: (result) => {
|
||||
console.log(result);
|
||||
},
|
||||
error: (err) => {
|
||||
reject(err.message);
|
||||
},
|
||||
complete: (result) => {
|
||||
resolve(qiniuConfig.domain + "/" + result.key);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export default {
|
||||
fileUpload,
|
||||
};
|
||||
|
269
src/assets/scripts/tokenTools.js
Normal file
269
src/assets/scripts/tokenTools.js
Normal file
@ -0,0 +1,269 @@
|
||||
export function utf16to8(str) {
|
||||
var out, i, len, c;
|
||||
out = "";
|
||||
len = str.length;
|
||||
for (i = 0; i < len; i++) {
|
||||
c = str.charCodeAt(i);
|
||||
if (c >= 0x0001 && c <= 0x007f) {
|
||||
out += str.charAt(i);
|
||||
} else if (c > 0x07ff) {
|
||||
out += String.fromCharCode(0xe0 | ((c >> 12) & 0x0f));
|
||||
out += String.fromCharCode(0x80 | ((c >> 6) & 0x3f));
|
||||
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3f));
|
||||
} else {
|
||||
out += String.fromCharCode(0xc0 | ((c >> 6) & 0x1f));
|
||||
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3f));
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export function utf8to16(str) {
|
||||
var out, i, len, c;
|
||||
var char2, char3;
|
||||
out = "";
|
||||
len = str.length;
|
||||
i = 0;
|
||||
while (i < len) {
|
||||
c = str.charCodeAt(i++);
|
||||
switch (c >> 4) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
// 0xxxxxxx
|
||||
out += str.charAt(i - 1);
|
||||
break;
|
||||
case 12:
|
||||
case 13:
|
||||
// 110x xxxx 10xx xxxx
|
||||
char2 = str.charCodeAt(i++);
|
||||
out += String.fromCharCode(((c & 0x1f) << 6) | (char2 & 0x3f));
|
||||
break;
|
||||
case 14:
|
||||
// 1110 xxxx 10xx xxxx 10xx xxxx
|
||||
char2 = str.charCodeAt(i++);
|
||||
char3 = str.charCodeAt(i++);
|
||||
out += String.fromCharCode(
|
||||
((c & 0x0f) << 12) |
|
||||
((char2 & 0x3f) << 6) |
|
||||
((char3 & 0x3f) << 0)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
var base64EncodeChars =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
||||
var base64DecodeChars = new Array(
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
62,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
63,
|
||||
52,
|
||||
53,
|
||||
54,
|
||||
55,
|
||||
56,
|
||||
57,
|
||||
58,
|
||||
59,
|
||||
60,
|
||||
61,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
15,
|
||||
16,
|
||||
17,
|
||||
18,
|
||||
19,
|
||||
20,
|
||||
21,
|
||||
22,
|
||||
23,
|
||||
24,
|
||||
25,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
26,
|
||||
27,
|
||||
28,
|
||||
29,
|
||||
30,
|
||||
31,
|
||||
32,
|
||||
33,
|
||||
34,
|
||||
35,
|
||||
36,
|
||||
37,
|
||||
38,
|
||||
39,
|
||||
40,
|
||||
41,
|
||||
42,
|
||||
43,
|
||||
44,
|
||||
45,
|
||||
46,
|
||||
47,
|
||||
48,
|
||||
49,
|
||||
50,
|
||||
51,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
);
|
||||
export function base64encode(str) {
|
||||
var out, i, len;
|
||||
var c1, c2, c3;
|
||||
len = str.length;
|
||||
i = 0;
|
||||
out = "";
|
||||
while (i < len) {
|
||||
c1 = str.charCodeAt(i++) & 0xff;
|
||||
if (i == len) {
|
||||
out += base64EncodeChars.charAt(c1 >> 2);
|
||||
out += base64EncodeChars.charAt((c1 & 0x3) << 4);
|
||||
out += "==";
|
||||
break;
|
||||
}
|
||||
c2 = str.charCodeAt(i++);
|
||||
if (i == len) {
|
||||
out += base64EncodeChars.charAt(c1 >> 2);
|
||||
out += base64EncodeChars.charAt(
|
||||
((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4)
|
||||
);
|
||||
out += base64EncodeChars.charAt((c2 & 0xf) << 2);
|
||||
out += "=";
|
||||
break;
|
||||
}
|
||||
c3 = str.charCodeAt(i++);
|
||||
out += base64EncodeChars.charAt(c1 >> 2);
|
||||
out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4));
|
||||
out += base64EncodeChars.charAt(((c2 & 0xf) << 2) | ((c3 & 0xc0) >> 6));
|
||||
out += base64EncodeChars.charAt(c3 & 0x3f);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export function base64decode(str) {
|
||||
var c1, c2, c3, c4;
|
||||
var i, len, out;
|
||||
len = str.length;
|
||||
i = 0;
|
||||
out = "";
|
||||
while (i < len) {
|
||||
/* c1 */
|
||||
do {
|
||||
c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
|
||||
} while (i < len && c1 == -1);
|
||||
if (c1 == -1) break;
|
||||
/* c2 */
|
||||
do {
|
||||
c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
|
||||
} while (i < len && c2 == -1);
|
||||
if (c2 == -1) break;
|
||||
out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
|
||||
/* c3 */
|
||||
do {
|
||||
c3 = str.charCodeAt(i++) & 0xff;
|
||||
if (c3 == 61) return out;
|
||||
c3 = base64DecodeChars[c3];
|
||||
} while (i < len && c3 == -1);
|
||||
if (c3 == -1) break;
|
||||
out += String.fromCharCode(((c2 & 0xf) << 4) | ((c3 & 0x3c) >> 2));
|
||||
/* c4 */
|
||||
do {
|
||||
c4 = str.charCodeAt(i++) & 0xff;
|
||||
if (c4 == 61) return out;
|
||||
c4 = base64DecodeChars[c4];
|
||||
} while (i < len && c4 == -1);
|
||||
if (c4 == -1) break;
|
||||
out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export function safe64(base64) {
|
||||
base64 = base64.replace(/\+/g, "-");
|
||||
base64 = base64.replace(/\//g, "_");
|
||||
return base64;
|
||||
}
|
@ -201,6 +201,66 @@
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane class="github-panel" label="七牛云 Kodo" name="qiniu">
|
||||
<el-form
|
||||
class="setting-form"
|
||||
ref="form"
|
||||
:model="formQiniu"
|
||||
label-position="right"
|
||||
label-width="140px"
|
||||
>
|
||||
<el-form-item label="AccessKey" :required="true">
|
||||
<el-input
|
||||
v-model.trim="formQiniu.accessKey"
|
||||
placeholder="如:6DD3VaLJ_SQgOdoocsyTV_YWaDmdnL2n8EGx7kG"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="SecretKey" :required="true">
|
||||
<el-input
|
||||
v-model.trim="formQiniu.secretKey"
|
||||
show-password
|
||||
placeholder="如:qgZa5qrvDOOcsmdKStD1oCjZ9nB7MDvJUs_34SIm"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Bucket" :required="true">
|
||||
<el-input
|
||||
v-model.trim="formQiniu.bucket"
|
||||
placeholder="如:md"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Bucket 对应域名" :required="true">
|
||||
<el-input
|
||||
v-model.trim="formQiniu.domain"
|
||||
placeholder="如:http://images.123ylb.cn"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="存储区域" :required="true">
|
||||
<el-input
|
||||
v-model.trim="formQiniu.region"
|
||||
placeholder="如:z2"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="存储路径" :required="false">
|
||||
<el-input
|
||||
v-model.trim="formQiniu.path"
|
||||
placeholder="如:img,可不填,默认为根目录"
|
||||
></el-input>
|
||||
<el-link
|
||||
type="primary"
|
||||
href="https://cloud.tencent.com/document/product/436/38484"
|
||||
target="_blank"
|
||||
>如何使用七牛云 Kodo?</el-link
|
||||
>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="saveQiniuConfiguration"
|
||||
>保存配置</el-button
|
||||
>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-dialog>
|
||||
</template>
|
||||
@ -238,6 +298,13 @@ export default {
|
||||
path: "",
|
||||
cdnHost: "",
|
||||
},
|
||||
formQiniu: {
|
||||
accessKey: "",
|
||||
secretKey: "",
|
||||
bucket: "",
|
||||
domain: "",
|
||||
region: "",
|
||||
},
|
||||
options: [
|
||||
{
|
||||
value: "default",
|
||||
@ -255,6 +322,10 @@ export default {
|
||||
value: "txCOS",
|
||||
label: "腾讯云",
|
||||
},
|
||||
{
|
||||
value: "qiniu",
|
||||
label: "七牛云",
|
||||
},
|
||||
],
|
||||
imgHost: "default",
|
||||
uploadingImg: false,
|
||||
@ -353,6 +424,30 @@ export default {
|
||||
});
|
||||
},
|
||||
|
||||
saveQiniuConfiguration() {
|
||||
if (
|
||||
!(
|
||||
this.formQiniu.accessKey &&
|
||||
this.formQiniu.secretKey &&
|
||||
this.formQiniu.bucket &&
|
||||
this.formQiniu.domain &&
|
||||
this.formQiniu.region
|
||||
)
|
||||
) {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: `七牛云 Kodo 参数配置不全`,
|
||||
type: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
localStorage.setItem("qiniuConfig", JSON.stringify(this.formQiniu));
|
||||
this.$message({
|
||||
message: "保存成功",
|
||||
type: "success",
|
||||
});
|
||||
},
|
||||
|
||||
// 图片上传前的处理
|
||||
beforeUpload(file) {
|
||||
if (!this.validateConfig()) {
|
||||
|
Loading…
Reference in New Issue
Block a user