Firebase Storage 圖床


notion permission denied - 403 error

之前弄的一個小工具可以把 Kobo 閱讀器的閱讀紀錄上傳到 Notion 管理。

在 Notion 整理 Kobo 電子書櫃與筆記

由於 Notion 不支援透過 API 上傳圖片到伺服器上,所以書籍封面原本是直接用 Kobo 的 CDN 網址。

但前陣子發現 Notion 突然沒辦法正常顯示這些圖片,懷疑是 Kobo 開始擋外站存取,所以乾脆自己弄一個圖床。

Firebase Storage 免費額度

撰文當下(2023 年)免費額度是 5GB 總容量,每日傳輸量 1GB。相當於一個月 30GB 的頻寬以圖床來說是真的滿少的,但我也就自己一個人使用而已,綽綽有餘。

firebase pricing

專案設定

開新專案就不特別紀錄了,Firebase 整個後台都有中文介面了,照著點就好。

由於我預計要從後端上傳圖片上去,所以會用到的是 Firebase Admin SDK 相關的東西,要記得去設定服務帳戶分頁最下面把金鑰下載下來,是個 json 檔。

Storage 設定

免費版只有一個 bucket,所以也沒得選,直接在根目錄開個資料夾當分類吧。

storage 本身有相當複雜的權限設定可以弄,但因為我寫入用的是 Admin SDK 不看這些權限設定,而讀取權限則是完全不限制,所以我就沒有特別去改動了。

CORS 的部分理論上也有一堆設定要改,但我沒改就能用了,有點不可思議。

關於 CORS 的官方設定教學:CORS Configuration

後端程式

後端一樣用 Node.js,所以用 npm 安裝 firebase-admin 開始作業

npm i firebase-admin --save

初始化

import { initializeApp } from "firebase-admin/app";
import { getStorage, getDownloadURL } from "firebase-admin/storage";
import admin from "firebase-admin";
import fs from "fs";

const key_path = "前面下載的金鑰的檔案路徑";
initializeApp({
  credential: admin.credential.cert(JSON.parse(fs.readFileSync(key_path))),
});

const bucket = getStorage().bucket("gs://專案名稱.appspot.com");

上傳

// Firebase Storage Upload
async upload(fileName, blob) {
    let file = bucket.file(fileName);
    await file.save(blob);
}

// 下載Kobo書籍封面然後上傳
const buffer = await (await fetch("圖片網址")).arrayBuffer();
await upload(imageName, new Uint8Array(buffer));

取得下載連結

這邊算踩到坑,由於之前有操作過 Amazon S3 的經驗,大概知道要呼叫類似 getSignedUrl 之類的方法去取得下載連結,結果產生的連結餵去 Notion 一樣無法顯示圖片?忙了一大圈結果回到原點?

後來才發現是自己自以為是,正確流程是這樣處理的:

async getUrl(fileName) {
    let file = bucket.file(fileName);
    return await getDownloadURL(file);
}

官方文件:Get a shareable download URL

Hi 喜歡這篇文章的話 可以按個讚或請我喝杯咖啡
Buy me a coffeeBuy me a coffee