選擇媒體儲存

本頁內容

為上傳的媒體選擇一個儲存配接器。資料庫備份包含媒體中繼資料而非儲存的檔案,因此請單獨備份儲存後端。

概覽

儲存使用場景簽章上傳
R2 繫結站點執行在 Cloudflare Workers 上
S3Node.js 站點使用 AWS S3、R2 的 S3 API、MinIO 或相容儲存
本機Node.js 站點有一個可寫的持久磁碟區

Cloudflare R2 繫結

在 Cloudflare Workers 上使用 R2 繫結配接器。繫結在執行時提供存取,因此站點不需要 R2 存取金鑰。

import emdash from "emdash/astro";
import { r2 } from "@emdash-cms/cloudflare";

export default defineConfig({
	integrations: [
		emdash({
			storage: r2({ binding: "MEDIA" }),
		}),
	],
});

設定

選項型別描述
bindingstringwrangler.jsonc 中的 R2 繫結名稱
publicUrlstring儲存桶的可選公開 URL

設定步驟

將 R2 繫結新增到 Wrangler 設定中:

wrangler.jsonc

{
  "r2_buckets": [
    {
      "binding": "MEDIA",
      "bucket_name": "emdash-media"
    }
  ]
}

wrangler.toml

[[r2_buckets]]
binding = "MEDIA"
bucket_name = "emdash-media"

公開存取

要從公開儲存桶提供媒體,使用 Cloudflare API 連接自訂網域,然後將其來源設定為 publicUrl。Cloudflare 的 r2.dev 開發 URL 有速率限制,不適用於正式流量。

storage: r2({
	binding: "MEDIA",
	publicUrl: "https://media.example.com",
});

如果同一儲存桶儲存自動 JSON 備份,公開儲存桶來源可能會暴露 backups/ 下的物件。請使用私有儲存桶和 EmDash 的媒體路由,或將公開來源限制為媒體物件。參見備份

S3 相容儲存

S3 配接器在 Node.js 上與 Cloudflare R2 的 S3 API、AWS S3、MinIO 和相容服務一起工作。

以下設定在 Node.js 程序啟動時從 S3_* 變數解析端點、儲存桶、憑證、區域和可選的公開 URL:

import emdash, { s3 } from "emdash/astro";

export default defineConfig({
	integrations: [
		emdash({
			storage: s3(),
		}),
	],
});

設定

選項型別必要描述
endpointstringS3 端點 URL
bucketstring儲存桶名稱
accessKeyIdstring否*存取金鑰
secretAccessKeystring否*秘密金鑰
regionstring區域(預設:"auto"
publicUrlstring可選的 CDN 或公開 URL

* accessKeyIdsecretAccessKey 必須同時提供或同時省略。

從環境變數解析 S3 設定

s3({...}) 中省略的任何欄位在程序啟動時從匹配的 S3_* 環境變數讀取。這允許您一次建置容器映像,在啟動時注入憑證而無需重新建置。s3({...}) 中的明確值始終優先於環境變數。

環境變數欄位備註
S3_ENDPOINTendpoint必須是有效的 http/https URL
S3_BUCKETbucket
S3_ACCESS_KEY_IDaccessKeyId
S3_SECRET_ACCESS_KEYsecretAccessKey
S3_REGIONregion預設為 "auto"
S3_PUBLIC_URLpublicUrl可選的 CDN 前綴

環境變數在程序啟動時從 process.env 讀取。這是僅限 Node 的功能。

呼叫不帶引數的 s3()S3_* 環境變數讀取每個欄位:

import emdash, { s3 } from "emdash/astro";

export default defineConfig({
	integrations: [
		emdash({
			// 無引數的 s3():所有欄位來自 S3_* 環境變數
			storage: s3(),

			// 或混合使用:覆寫一個欄位,其餘來自環境
			// storage: s3({ publicUrl: "https://cdn.example.com" }),
		}),
	],
});

透過 S3 API 使用 R2

當需要直接簽章上傳到 R2 時,在 Node.js 上使用 S3 配接器。使用 Cloudflare API 或 CLI 建立範圍受限的 R2 API 憑證,然後設定以下執行時變數:

S3_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
S3_BUCKET=emdash-media
S3_ACCESS_KEY_ID=<r2-access-key-id>
S3_SECRET_ACCESS_KEY=<r2-secret-access-key>
S3_REGION=auto
S3_PUBLIC_URL=https://media.example.com

將真實值保存在 Node.js 託管平台的密鑰管理器中。公開 URL 是可選的,不會取代用於上傳的 S3 API 端點。

MinIO

將相同的執行時變數指向 MinIO。將 S3_ENDPOINT 設為 MinIO API 來源,S3_BUCKET 設為儲存桶名稱,兩個憑證變數設為範圍受限的 MinIO 存取金鑰。僅當該來源公開提供儲存桶物件時才設定 S3_PUBLIC_URL

本機檔案系統

使用本機儲存進行開發或用於具有持久磁碟的單一 Node.js 伺服器。檔案儲存在該磁碟上的目錄中。

import emdash, { local } from "emdash/astro";

export default defineConfig({
	integrations: [
		emdash({
			storage: local({
				directory: "./uploads",
				baseUrl: "/_emdash/api/media/file",
			}),
		}),
	],
});

設定

選項型別描述
directorystring檔案儲存的目錄路徑
baseUrlstring提供檔案的基礎 URL

baseUrl 應與 EmDash 的媒體檔案端點 (/_emdash/api/media/file) 匹配,除非你設定了自訂靜態檔案伺服器。

為不同環境使用不同的儲存

以下設定在開發期間使用本機目錄,在 Cloudflare 正式建置中使用 R2:

import emdash, { local } from "emdash/astro";
import { r2 } from "@emdash-cms/cloudflare";

const storage = import.meta.env.PROD
	? r2({ binding: "MEDIA" })
	: local({
			directory: "./uploads",
			baseUrl: "/_emdash/api/media/file",
		});

export default defineConfig({
	integrations: [emdash({ storage })],
});

簽章上傳

S3 配接器支援簽章上傳 URL,允許用戶端直接上傳到儲存而不經過伺服器。這提高了大型檔案的效能。

使用 S3 配接器時簽章上傳是自動的。管理介面在可用時使用它們。

支援簽章上傳的配接器:

  • S3(包括透過 S3 API 的 R2)

不支援簽章上傳的配接器:

  • R2 繫結(請改用帶有 R2 憑證的 S3 配接器)
  • 本機

儲存介面

所有儲存配接器實作相同的介面:

interface Storage {
	upload(options: {
		key: string;
		body: Buffer | Uint8Array | ReadableStream;
		contentType: string;
	}): Promise<UploadResult>;

	download(key: string): Promise<DownloadResult>;
	delete(key: string): Promise<void>;
	exists(key: string): Promise<boolean>;
	list(options?: ListOptions): Promise<ListResult>;
	getSignedUploadUrl(options: SignedUploadOptions): Promise<SignedUploadUrl>;
	getPublicUrl(key: string): string;
}

這種一致性允許在不變更應用程式碼的情況下切換儲存後端。