本文首發(fā)于個(gè)人博客https://www.kagurakana.xyz/detail/e169338c7,如果對(duì)您有幫助,或者任何建議,請(qǐng)務(wù)必在小站流言,一起做朋友呀~~
圖床介紹
圖床是我這種小博客賴以生存的工具,他可以托管圖片,減輕我的1核2g的辣雞服務(wù)器的壓力.目前我使用過的圖床有sm.ms,和七牛cdn,而七牛不只可以托管圖片,還可以托管各種靜態(tài)資源,例如音頻和視頻等.并為其綁定加速域名.以下主要介紹七牛JavaScript-sdk和node-sdk.因?yàn)楸静┛筒捎昧薾ode作為后端.
十分雞肋的是七牛cdn每個(gè)月只有10g的靜態(tài)資源存儲(chǔ)空間(不累加),用超出去會(huì)每個(gè)月交錢(10G大概1.5元,如果每個(gè)月存儲(chǔ)100G也就15塊),其他的作為小站來說基本不可能達(dá)到,具體資費(fèi)請(qǐng)參照官網(wǎng).
準(zhǔn)備工作
1. 注冊(cè)七牛賬號(hào),創(chuàng)建存儲(chǔ)空間bucket
首先選擇對(duì)象存儲(chǔ),并創(chuàng)建存儲(chǔ)空間.
點(diǎn)擊新建空間,進(jìn)行一些簡(jiǎn)單的配置,如選擇存儲(chǔ)地理位置等,配置完成后就會(huì)看到下面的存儲(chǔ)空間,此時(shí)已經(jīng)可以手動(dòng)添加圖片進(jìn)去了.
2. 綁定域名加速
在創(chuàng)建好bucket也就是存儲(chǔ)空間之后,可以進(jìn)行域名加速綁定,好處是可以使用自己的域名進(jìn)行圖片獲取和上傳.
綁定的域名需要在大陸進(jìn)行ICP備案,我的域名是kagurakana.xyz,在阿里云購買,SSL證書是阿里云免費(fèi)個(gè)人版證書,這種證書只支持單域名,不支持泛域名(*.domain.com),如果你和我一樣需要https
協(xié)議來存儲(chǔ)你的圖片,除了本站域名(kagurakana.xyz)需要申請(qǐng)SSL證書之外,cdn域名(我的是cdn.kagurakana.xyz,可以在阿里云的dns解析中配置)也要申請(qǐng)SSL證書,假設(shè)你現(xiàn)在已經(jīng)有了yourdomain.com
和cdn.yourdomain.com
的ssl證書.且主站yourdomain.com
已經(jīng)在域名購買商的dns解析中和Nginx服務(wù)器中完成了配置(如何在主站中配置https和Nginx部署SSL我會(huì)在最近寫一篇文章介紹),那么只需要關(guān)注cdn.yourdomain.com
的證書就好了,這個(gè)不需要進(jìn)行配置,只要下載下來復(fù)制到七牛cdn中就好了,我會(huì)在后面介紹.
2.1 配置七牛云域名加速
可以按照喜好自行配置.
2.2 *申請(qǐng)?jiān)撚蛎腟SL(HTTPS需要/HTTP可跳過)
在阿里云申請(qǐng)個(gè)人免費(fèi)版SSL證書,填寫證書域名為cdn.yourdomain.com
,其他默認(rèn)就好,證書文件會(huì)自動(dòng)關(guān)聯(lián)到到你的cdn域名下.下載Nginx版的證書文件,其中會(huì)有一個(gè).pem
文件和一個(gè).key
文件.先保存在本地.
2.3 *在七牛CDN導(dǎo)入證書文件(HTTPS需要/HTTP可跳過)
把剛才先下載的.pem
中的內(nèi)容用編輯器打開,復(fù)制到證書內(nèi)容一欄,把.key
文件打開復(fù)制到證書密鑰一欄,點(diǎn)添加.添加完成后應(yīng)該可以看到cdn頁面下的https證書多了一個(gè)可以選的,選擇那個(gè).
后面的原站配置選擇七牛云存儲(chǔ),其他選擇默認(rèn)或者推薦就好.在高級(jí)配置中可選擇域名防盜鏈,防止被引用過多產(chǎn)生更多費(fèi)用,我配置了本站(kagurakana.xyz)和簡(jiǎn)書和七牛云這三個(gè).
2.4 配置阿里云域名的DNS解析
在七牛的cdn配置完之后,要將圖片cdn和主站DNS進(jìn)行關(guān)聯(lián),在七牛完成之后,可以得到一個(gè)CNAME值,復(fù)制這個(gè)CNAME
上到阿里云的控制臺(tái),找到DNS,記錄類型選擇CNAME,將剛才的CNAME填入下面的記錄字中.
等待DNS服務(wù)器更新(TTL時(shí)間)后,可以看到狀態(tài)從等待CNAME成為了成功.
至此,準(zhǔn)備階段的工作全部完成,你可以用你自定義的域名來訪問上傳的圖片了,然而這是不夠的.我們還要解決圖片拖拽自動(dòng)上傳的功能.
使用JavaScript-SDK和node-SDK完成自動(dòng)上傳
1. 后端鑒權(quán)
安裝七牛cdn
npm install qiniu --save
創(chuàng)建qiniu.config.js
文件:
// /config/qiniu.config.js
module.exports = {
accessKey: '在七牛個(gè)人信息密鑰管理中可以找到',
secretKey: '在七牛個(gè)人信息密鑰管理中可以找到',
domain: '在bucket管理界面可以找到,可以看下面的圖片',
options: {
scope: "kagurakana",//你的bucket空間的名稱
expires: 3 * 3600,//單次鑒權(quán)有效期,在申請(qǐng)鑒權(quán)的多少喵內(nèi)可以上傳,可缺省,默認(rèn)為1小時(shí)
//自定義返回參數(shù),在上傳成功后返回給前端,注意是字符串類型,是$()小括號(hào)不是大括號(hào),大括號(hào)沒試過不知道行不行.
//其中$(key),$(bucket),$(fname)是七牛中的默認(rèn)變量
//
returnBody: `{"key":"$(key)",
"bucket":"$(bucket)",
"name":"$(fname)"}`
}
}
更詳細(xì)的配置可以在官網(wǎng)里找到,這里只列的我的配置.
在router中引入
// /routes/update.js
let express = require('express');
let router = express.Router()
//導(dǎo)入之前的config
let opt = require('../config/qiniu.js')
let qiniu = require('qiniu');
//我自己的管理員權(quán)限認(rèn)證中間件
const {loginCheckAdmin} = require('../midware/midware')
// 定義鑒權(quán)對(duì)象mac
let mac = new qiniu.auth.digest.Mac(opt.accessKey,opt.secretKey)
// 定義上傳憑證
let putPolicy = new qiniu.rs.PutPolicy(opt.options)
let uploadToken = putPolicy.uploadToken(mac)
//處理get獲取上傳鑒權(quán)認(rèn)證,我這里是管理員才能上傳
//你也可以寫中間件只能讓注冊(cè)用戶上傳.或者開放上傳(避免濫用不推薦)
router.get('/uptoken',loginCheckAdmin,(req,res,next)=>{
res.header("Cache-Control", "max-age=0, private, must-revalidate");
res.header("Pragma", "no-cache");
res.header("Expires", 0);
if(uploadToken) {
res.json({uploadToken});
}
})
module.exports = router;
后端最簡(jiǎn)單的配置已經(jīng)結(jié)束了,如果還需要添加文字或圖片水印,裁剪圖片,加濾鏡,生成縮略圖,覆蓋重復(fù)文件可以參考node-SDK文檔
.
2. 前端上傳
前端使用了vue+axios,可以根據(jù)配置自行修改
npm install qiniu-js --save
封裝網(wǎng)絡(luò)請(qǐng)求請(qǐng)求鑒權(quán)
//封裝網(wǎng)絡(luò)請(qǐng)求request方法,僅提供參考.
// network/request.js
import axios from 'axios'
axios.defaults.withCredentials=true;//配置axios攜帶cookie
export function request(config){
const instance = axios.create({
baseURL:'https://yourdomaim.com/apis',
timeout:5000
})
//攔截
instance.interceptors.response.use(res=>{
if(res.data.errno!=404){
return res.data;
}else{
window.location.replace('/home')
}
})
return instance(config)
}
// network/imgUpdate.js
import { request } from './request'
export function getUploadToken(){
return request({
method:'get',
url:'你的后端接口/uptoken'
})
}
拖拽上傳
首先來看一下sdk提供的上傳函數(shù):
qiniu.upload(file: blob, key: string, token: string, putExtra: object, config: object): observable`
上面的關(guān)鍵函數(shù)返回一個(gè)觀察者對(duì)象(observable),該對(duì)象具有訂閱(subscribe)方法,subscribe方法接收三個(gè)函數(shù)作為參數(shù),分別在上傳中,上傳失敗,上傳成功后調(diào)用.
//界面.vue
<template>
<!-- 監(jiān)聽拖放事件 -->
<v-textarea @drop.prevent.stop="imgDrop" v-model="content" label="content"></v-textarea>
</template>
<script>
import { getUploadToken } from "network/imgUpdate";
import * as qiniu from "qiniu-js";
export default {
name: "BlogPost",
data() {
return {
upToken: "",
content:""
};
},
created() {
getUploadToken().then(res => {
//獲取后臺(tái)返回的七牛cdn uptoken
this.upToken = res.data.uploadToken;
});
},
methods: {
//這三個(gè)方法作為參數(shù)給七牛觀察方法傳遞的,不能缺省
//上傳錯(cuò)誤處理調(diào)用的(七牛返回的錯(cuò)誤信息)
next(res){
//可以自己log下res,是上傳的進(jìn)度什么的;
},
error(err) {
console.log(err);
},
//成功處理后調(diào)用的方法
complete(res) {
//url拼接,返回markdown格式字符串,content是雙向綁定數(shù)據(jù),更進(jìn)一步,你可以根據(jù)輸入的光標(biāo)位置決定markdown位置
this.content += `![${res.name}](https://cdn.kagurakana.xyz/${res.name})`;
},
/**拖放監(jiān)聽處理chorme,其他未做適配 */
imgDrop(e) {
//這里如果console.log(e)里面dataTransfer的files數(shù)組是空的,不用管
let file = e.dataTransfer.files[0]; //獲取拖放文件 Blob
if (this.upToken) {
//函數(shù)格式:qiniu.upload(file: blob, key: string, token: string, putExtra: object, config: object): observable
let observable = qiniu.upload(
file,
file.name,
this.upToken,
{ fname: file.name, params: {}, mimeType: null }, //putExtra
{ useCdnDomain: true } //config
);
//開始上傳
observable.subscribe(this.next,this.error,this.complete);
}
}
}
};
</script>
<style lang='scss' scoped>
</style>
看一下效果:
更進(jìn)一步,你可以添加剪貼板上傳圖片而不是拖拽上傳,或者根據(jù)光標(biāo)位置插入markdown而不是在末尾插入.