feat: upload image by minio (#131)

This commit is contained in:
李寻欢 2022-02-14 00:12:07 +08:00 committed by GitHub
parent 4f296d6145
commit e6cc11d67b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 176 additions and 30 deletions

View File

@ -46,14 +46,15 @@ Markdown 文档自动即时渲染为微信图文,让你不再为微信文章
## 目前支持哪些图床 ## 目前支持哪些图床
| # | 图床 | 使用时是否需要配置 | 备注 | | # | 图床 | 使用时是否需要配置 | 备注 |
| --- | ----------------------------------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | | --- | ----------------------------------------------- | -------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| 1 | 默认 | 否 | - | | 1 | 默认 | 否 | - |
| 2 | [Gitee](https://gitee.com) | 配置 `Repo`、`Token` 参数 | 图片超过 1MB 无法正常展示 | | 2 | [Gitee](https://gitee.com) | 配置 `Repo`、`Token` 参数 | 图片超过 1MB 无法正常展示 |
| 3 | [GitHub](https://github.com) | 配置 `Repo`、`Token` 参数 | [如何获取 GitHub token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) | | 3 | [GitHub](https://github.com) | 配置 `Repo`、`Token` 参数 | [如何获取 GitHub token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) |
| 4 | [阿里云](https://www.aliyun.com/product/oss) | 配置 `AccessKey ID`、`AccessKey Secret`、`Bucket`、`Region` 参数 | [如何使用阿里云 OSS](https://help.aliyun.com/document_detail/31883.html) | | 4 | [阿里云](https://www.aliyun.com/product/oss) | 配置 `AccessKey ID`、`AccessKey Secret`、`Bucket`、`Region` 参数 | [如何使用阿里云 OSS](https://help.aliyun.com/document_detail/31883.html) |
| 5 | [腾讯云](https://cloud.tencent.com/act/pro/cos) | 配置 `SecretId`、`SecretKey`、`Bucket`、`Region` 参数 | [如何使用腾讯云 COS](https://cloud.tencent.com/document/product/436/38484) | | 5 | [腾讯云](https://cloud.tencent.com/act/pro/cos) | 配置 `SecretId`、`SecretKey`、`Bucket`、`Region` 参数 | [如何使用腾讯云 COS](https://cloud.tencent.com/document/product/436/38484) |
| 6 | [七牛云](https://www.qiniu.com/products/kodo) | 配置 `AccessKey`、`SecretKey`、`Bucket`、`Domain`、`Region` 参数 | [如何使用七牛云 Kodo](https://developer.qiniu.com/kodo) | | 6 | [七牛云](https://www.qiniu.com/products/kodo) | 配置 `AccessKey`、`SecretKey`、`Bucket`、`Domain`、`Region` 参数 | [如何使用七牛云 Kodo](https://developer.qiniu.com/kodo) |
| 7 | 自定义上传 | 是 | [如何自定义上传?](#自定义上传逻辑) | | 7 | [MinIO](https://min.io/) | 配置 `Endpoint`、`Port`、`UseSSL`、`Bucket`、`AccessKey`、`SecretKey` 参数 | [如何使用 MinIO](http://docs.minio.org.cn/docs/master/minio-client-complete-guide) |
| 8 | 自定义上传 | 是 | [如何自定义上传?](#自定义上传逻辑) |
![select-and-change-color-theme](https://doocs.oss-cn-shenzhen.aliyuncs.com/img//1606034542281-a8c99fa7-c11e-4e43-98da-e36012f54dc8.gif) ![select-and-change-color-theme](https://doocs.oss-cn-shenzhen.aliyuncs.com/img//1606034542281-a8c99fa7-c11e-4e43-98da-e36012f54dc8.gif)

View File

@ -25,6 +25,7 @@
"jquery": "^3.6.0", "jquery": "^3.6.0",
"juice": "^8.0.0", "juice": "^8.0.0",
"marked": "^4.0.10", "marked": "^4.0.10",
"minio": "^7.0.26",
"node-fetch": "^3.1.0", "node-fetch": "^3.1.0",
"prettier": "^2.5.1", "prettier": "^2.5.1",
"prettify": "^0.1.7", "prettify": "^0.1.7",

View File

@ -2,6 +2,7 @@ import fetch from "./fetch";
import { githubConfig, giteeConfig } from "./config"; import { githubConfig, giteeConfig } from "./config";
import CryptoJS from "crypto-js"; import CryptoJS from "crypto-js";
import OSS from "ali-oss"; import OSS from "ali-oss";
import * as Minio from "minio";
import COS from "cos-js-sdk-v5"; import COS from "cos-js-sdk-v5";
import Buffer from "buffer-from"; import Buffer from "buffer-from";
import { v4 as uuidv4 } from "uuid"; import { v4 as uuidv4 } from "uuid";
@ -182,8 +183,8 @@ async function aliOSSFileUpload(content, filename) {
}); });
try { try {
const res = await client.put(dir, buffer); const res = await client.put(dir, buffer);
if (cdnHost == "") return res.url; if (cdnHost === "") return res.url;
return `${cdnHost}/${path == "" ? dateFilename : dir}`; return `${cdnHost}/${path === "" ? dateFilename : dir}`;
} catch (e) { } catch (e) {
return Promise.reject(e); return Promise.reject(e);
} }
@ -227,6 +228,48 @@ async function txCOSFileUpload(file) {
}); });
} }
//-----------------------------------------------------------------------
// Minio File Upload
//-----------------------------------------------------------------------
async function minioFileUpload(content, filename) {
const dateFilename = getDateFilename(filename);
const { endpoint, port, useSSL, bucket, accessKey, secretKey } = JSON.parse(
localStorage.getItem("minioConfig")
);
const buffer = Buffer(content, "base64");
const conf = {
endPoint: endpoint,
useSSL: useSSL,
accessKey: accessKey,
secretKey: secretKey,
};
const p = Number(port || 0);
const isCustomPort = p > 0 && p !== 80 && p !== 443;
if (isCustomPort) {
conf.port = p;
}
return new Promise((resolve, reject) => {
const minioClient = new Minio.Client(conf);
try {
minioClient.putObject(bucket, dateFilename, buffer, function (e) {
if (e) {
reject(e);
}
const host = `${useSSL ? "https://" : "http://"}${endpoint}${
isCustomPort ? ":" + port : ""
}`;
const url = `${host}/${bucket}/${dateFilename}`;
// console.log("文件上传成功: ", url)
resolve(url);
// return `${endpoint}/${bucket}/${dateFilename}`;
});
} catch (e) {
reject(e);
}
});
}
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
// formCustom File Upload // formCustom File Upload
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
@ -269,6 +312,8 @@ function fileUpload(content, file) {
switch (imgHost) { switch (imgHost) {
case "aliOSS": case "aliOSS":
return aliOSSFileUpload(content, file.name); return aliOSSFileUpload(content, file.name);
case "minio":
return minioFileUpload(content, file.name);
case "txCOS": case "txCOS":
return txCOSFileUpload(file); return txCOSFileUpload(file);
case "qiniu": case "qiniu":

View File

@ -288,7 +288,70 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-tab-pane> </el-tab-pane>
<el-tab-pane class="github-panel formCustom" label="自定义代码" name="formCustom"> <el-tab-pane class="github-panel" label="MinIO" name="minio">
<el-form
class="setting-form"
:model="minioOSS"
label-position="right"
label-width="140px"
>
<el-form-item label="Endpoint" :required="true">
<el-input
v-model.trim="minioOSS.endpoint"
placeholder="如play.min.io"
></el-input>
</el-form-item>
<el-form-item label="Port" :required="false">
<el-input
type="number"
v-model.trim="minioOSS.port"
placeholder="如9000可不填http 默认为 80https 默认为 443"
></el-input>
</el-form-item>
<el-form-item label="UseSSL" :required="true">
<el-switch
v-model="minioOSS.useSSL"
active-text="是"
inactive-text="否"
>
</el-switch>
</el-form-item>
<el-form-item label="Bucket" :required="true">
<el-input
v-model.trim="minioOSS.bucket"
placeholder="如doocs"
></el-input>
</el-form-item>
<el-form-item label="AccessKey" :required="true">
<el-input
v-model.trim="minioOSS.accessKey"
placeholder="如zhangsan"
></el-input>
</el-form-item>
<el-form-item label="SecretKey" :required="true">
<el-input
v-model.trim="minioOSS.secretKey"
placeholder="如asdasdasd"
></el-input>
<el-link
type="primary"
href="http://docs.minio.org.cn/docs/master/minio-client-complete-guide"
target="_blank"
>如何使用 MinIO</el-link
>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="saveMinioOSSConfiguration"
>保存配置</el-button
>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane
class="github-panel formCustom"
label="自定义代码"
name="formCustom"
>
<el-form <el-form
class="setting-form" class="setting-form"
:model="formCustom" :model="formCustom"
@ -301,7 +364,8 @@
type="textarea" type="textarea"
resize="none" resize="none"
placeholder="Your custom code here." placeholder="Your custom code here."
v-model="formCustom.code"> v-model="formCustom.code"
>
</el-input> </el-input>
<el-link <el-link
type="primary" type="primary"
@ -354,6 +418,14 @@ export default {
path: "", path: "",
cdnHost: "", cdnHost: "",
}, },
minioOSS: {
endpoint: "",
port: "",
useSSL: true,
bucket: "",
accessKey: "",
secretKey: "",
},
formTxCOS: { formTxCOS: {
secretId: "", secretId: "",
secretKey: "", secretKey: "",
@ -370,7 +442,9 @@ export default {
region: "", region: "",
}, },
formCustom: { formCustom: {
code: localStorage.getItem(`formCustomConfig`) || removeLeft(` code:
localStorage.getItem(`formCustomConfig`) ||
removeLeft(`
const {file, util, okCb, errCb} = CUSTOM_ARG const {file, util, okCb, errCb} = CUSTOM_ARG
const param = new FormData() const param = new FormData()
param.append('file', file) param.append('file', file)
@ -409,6 +483,10 @@ export default {
value: "qiniu", value: "qiniu",
label: "七牛云", label: "七牛云",
}, },
{
value: "minio",
label: "MinIO",
},
{ {
value: "formCustom", value: "formCustom",
label: "自定义代码", label: "自定义代码",
@ -427,6 +505,9 @@ export default {
if (localStorage.getItem("aliOSSConfig")) { if (localStorage.getItem("aliOSSConfig")) {
this.formAliOSS = JSON.parse(localStorage.getItem("aliOSSConfig")); this.formAliOSS = JSON.parse(localStorage.getItem("aliOSSConfig"));
} }
if (localStorage.getItem("minioConfig")) {
this.minioOSS = JSON.parse(localStorage.getItem("minioConfig"));
}
if (localStorage.getItem("txCOSConfig")) { if (localStorage.getItem("txCOSConfig")) {
this.formTxCOS = JSON.parse(localStorage.getItem("txCOSConfig")); this.formTxCOS = JSON.parse(localStorage.getItem("txCOSConfig"));
} }
@ -472,7 +553,21 @@ export default {
localStorage.setItem("aliOSSConfig", JSON.stringify(this.formAliOSS)); localStorage.setItem("aliOSSConfig", JSON.stringify(this.formAliOSS));
this.$message.success("保存成功"); this.$message.success("保存成功");
}, },
saveMinioOSSConfiguration() {
if (
!(
this.minioOSS.endpoint &&
this.minioOSS.bucket &&
this.minioOSS.accessKey &&
this.minioOSS.secretKey
)
) {
this.$message.error(`MinIO 参数配置不全`);
return;
}
localStorage.setItem("minioConfig", JSON.stringify(this.minioOSS));
this.$message.success("保存成功");
},
saveTxCOSConfiguration() { saveTxCOSConfiguration() {
if ( if (
!( !(
@ -506,9 +601,9 @@ export default {
this.$message.success("保存成功"); this.$message.success("保存成功");
}, },
formCustomSave() { formCustomSave() {
const str = this.formCustom.editor.getValue() const str = this.formCustom.editor.getValue();
localStorage.setItem(`formCustomConfig`, str) localStorage.setItem(`formCustomConfig`, str);
this.$message.success(`保存成功`) this.$message.success(`保存成功`);
}, },
beforeImageUpload(file) { beforeImageUpload(file) {
@ -539,21 +634,22 @@ export default {
activeName: { activeName: {
immediate: true, immediate: true,
handler(val) { handler(val) {
if(val === `formCustom`) { if (val === `formCustom`) {
this.$nextTick(() => { this.$nextTick(() => {
const textarea = this.$refs.formCustomElInput.$el.querySelector(`textarea`) const textarea =
this.formCustom.editor = this.formCustom.editor || CodeMirror.fromTextArea(textarea, { this.$refs.formCustomElInput.$el.querySelector(`textarea`);
this.formCustom.editor =
this.formCustom.editor ||
CodeMirror.fromTextArea(textarea, {
mode: `javascript`, mode: `javascript`,
}) });
this.formCustom.editor.setValue(this.formCustom.code) this.formCustom.editor.setValue(this.formCustom.code);
}) });
} }
}, },
}, },
}, },
mounted() { mounted() {},
},
}; };
</script> </script>
@ -600,7 +696,8 @@ export default {
/deep/ .CodeMirror { /deep/ .CodeMirror {
border: 1px solid #eee; border: 1px solid #eee;
height: 300px !important; height: 300px !important;
font-family: "Fira Mono", "DejaVu Sans Mono", Menlo, Consolas, "Liberation Mono", Monaco, "Lucida Console", monospace !important; font-family: "Fira Mono", "DejaVu Sans Mono", Menlo, Consolas,
"Liberation Mono", Monaco, "Lucida Console", monospace !important;
line-height: 20px; line-height: 20px;
.CodeMirror-scroll { .CodeMirror-scroll {
padding: 10px; padding: 10px;

View File

@ -267,6 +267,7 @@ export default {
fileApi fileApi
.fileUpload(base64Content, file) .fileUpload(base64Content, file)
.then((url) => { .then((url) => {
console.log(url)
this.uploaded(url); this.uploaded(url);
}) })
.catch((err) => { .catch((err) => {
@ -280,6 +281,7 @@ export default {
}, },
// //
uploaded(response) { uploaded(response) {
console.log("图片上传之后: ", response)
if (!response) { if (!response) {
this.$message.error("上传图片未知异常"); this.$message.error("上传图片未知异常");
return; return;