有了圖牀,讓你寫博客更舒服!

這篇文章給大家分享的是個人用自建圖牀搭建過程。

圖牀,也就是專門提供存儲圖片的地方,我們只要通過圖牀提供的 API 接口,把圖片上傳上去,就可以通過外鏈訪問了,我們在CSDN發表文章,上傳圖片,其實就是用的CSDN的圖牀,但CSDN的圖牀有時候也挺不方便的。

比如,在我剛開始寫博客的時候,我喜歡先在本地寫,博客中的圖片我都存儲在本地的文件夾裏。

然後在本地寫完了,保存爲.md文件。

再打開CSDN、上傳Markdown,然後就會出現這樣的錯誤:

如果一篇文章的圖片多起來,事情就麻煩了,有時候還會漏掉一些圖片。

如果我們自己搭建圖牀,直接把這些圖片存儲在雲端,圖片的來源是http服務,就沒有這些問題了,本文就是以該思路來提供一個解決方案。

最終效果如下:

爲了實現這樣的效果,你需要:

  • 一點Node.js的知識
  • 一臺VPS服務器,Linux、Windows都可以(本文使用的是Win Server、坑比Linux要多得多)
  • 本文僅用作Mac用戶作參考,因爲用到了upic(開源圖牀客戶端)

下載並且安裝uPic

uPic(upload Picture) 是一款 Mac 端的圖牀(文件)上傳客戶端,可以將圖片、各種文件上傳到配置好的指定提供商的對象存儲中。
然後快速獲取可供互聯網訪問的文件 URL

不要去APP Store下載。

點擊這個鏈接,前往Github下載dmg文件。

或者使用HomeBrew安裝

brew cask install upic

在VPS服務器上安裝minio

minio是可以部署在本地的對象存儲服務。

根據VPS的系統不同,在官方文檔裏都能夠找到對應的安裝方法。

Mac和Linux安裝都很方便,Windows下載下來就是一個exe,都不帶安裝過程的。

在CMD裏啓動服務:

./minio.exe server ./data

其中./data是指定的對象存儲的文件所在位置。

打開之後默認會偵聽9000端口,訪問該端口可以進入服務。

然後,Win比較頭疼的是如何將這句話變成一個服務,畢竟你總不能一直掛個命令行在上面吧。

先創建一個minio.bat文件,然後寫入如下內容

@echo off
set MINIO_ACCESS_KEY=access_key
set MINIO_SECRET_KEY=secret_key
C:\Users\Administrator\Desktop\個人網站\minio.exe server C:\Users\Administrator\Desktop\個人網站\文件共享

將第四行的兩個絕對路徑分別替換成minio的路徑和對象存儲的路徑即可。

然後可以運行一下./minio.bat看看是否能夠成功運行。

要注意MINIO_ACCESS_KEYMINIO_SECRET_KEY這兩個參數,相當於minio的用戶名和密碼。

然後我們將這個腳本註冊成服務,使用cmd的sc命令,格式如下:

sc create minioServer binpath=C:\Users\Administrator\Desktop\個人網站\minio.bat start=auto 

同樣,把腳本的絕對路徑替換成自己的。

這樣我們就註冊完服務,在服務管理頁面能夠看到該服務了,可以設置爲開機自啓動。

編寫Nodejs後端

代碼很簡單,使用的Expressjs,抄的學長的代碼

const express = require('express')
const multer  = require('multer')
const Minio = require('minio')
const path = require('path')
const fs = require('fs')

const upload = multer({ dest: './tmp/' })
upload.limits = {
    fileSize: 10 * 1024 * 1024 // 最大 10MB
}

const app = express()

// minio 客戶端
const minioClient = new Minio.Client({
    endPoint: 'xxxxxx', // 替換 minio 的訪問地址
    port: 9000,
    useSSL: false,
    accessKey: 'xxxxx', // 替換 accessKey
    secretKey: 'xxxxxx' // 替換 secretKey
});

const handleError = (err, res) => {
    res
        .status(500)
        .contentType("text/plain")
        .end("Oops! Something went wrong!");
};

app.post('/', upload.single('file'), function(req, res, next) {
    // 檢查 token
    const token = req.get('token')
    if (token !== 'xxxxxxx') { // 替換鑑權 token
        return handleError('', res)
    }
    // 文件臨時存儲文件夾
    const {originalname, path: tmpPath} = req.file
    // 文件後綴
    const extname = path.extname(originalname).toLowerCase()

    if (['.png', '.jpg', '.jpeg', '.gif'].indexOf(extname) !== -1) {
        // minio 中保存的文件名
        const filePath =  `${tmpPath}.${extname}`
        // 獲取月份
        const today = new Date()
        const month = today.getMonth() + 1
        const year = today.getFullYear()
        // 重命名文件
        fs.rename(tmpPath, filePath,  err => {
            if (err) return handleError(err, res)
            // 上傳指 minio 中
            minioClient.fPutObject("resource", `img/${year}/${month}/${originalname}`, filePath, {
                'Content-Type': `image/${extname.split('.')[1]}`,
            }, async () => {
                await fs.unlink(filePath, function() {})
                res.json({
                    "data": `http://ip/resource/img/${year}/${month}/${originalname}` // 替換 ip
                })
            })
        });
    } else {
        // 刪除文件
        fs.unlink(tmpPath, err => {
            if (err) return handleError(err, res);
        })
        res.status(403).contentType("text/plain").end("Only img files are allowed!");
    }
})

app.listen(3002, () => {
    console.log("app listening on port 3002")
})

然後用pm2部署一下就ok了。

我們偵聽的是3002端口,實際上有域名的話可以做個轉發,這裏我就不多講了。

uPic客戶端配置

image-20200427002819589

點擊其他字段新增一個Header

注意:這裏的token字段是在nodejs代碼中設置的。

然後驗證一下:

並且能夠支持截圖、剪貼板、文件上傳,很完美!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章