EmDash 將上傳的媒體(圖片、文件、影片)儲存在可設定的儲存後端中。根據您的部署平台和需求進行選擇。
概述
| 儲存 | 最適合 | 特性 |
|---|---|---|
| R2 Binding | Cloudflare Workers | 零設定,快速 |
| S3 | 任何平台 | 簽名上傳,CDN 支援 |
| Local | 開發環境 | 簡單的檔案系統儲存 |
Cloudflare R2 (Binding)
在部署到 Cloudflare Workers 時使用 R2 繫結以獲得最快的整合。
import emdash from "emdash/astro";
import { r2 } from "@emdash-cms/cloudflare";
export default defineConfig({
integrations: [
emdash({
storage: r2({ binding: "MEDIA" }),
}),
],
});
設定
| 選項 | 類型 | 描述 |
|---|---|---|
binding | string | 來自 wrangler.jsonc 的 R2 繫結名稱 |
publicUrl | string | 儲存桶的選用公開 URL |
設置
將 R2 繫結新增到您的 Wrangler 設定中:
wrangler.jsonc
{
"r2_buckets": [
{
"binding": "MEDIA",
"bucket_name": "emdash-media"
}
]
} wrangler.toml
[[r2_buckets]]
binding = "MEDIA"
bucket_name = "emdash-media" 公開存取
對於公開媒體 URL,在您的 R2 儲存桶上啟用公開存取:
- 前往 Cloudflare 控制面板 > R2 > 您的儲存桶
- 在設定中啟用公開存取
- 將公開 URL 新增到您的設定中:
storage: r2({
binding: "MEDIA",
publicUrl: "https://pub-xxxx.r2.dev",
});
S3 相容儲存
S3 配接器適用於 Cloudflare R2(透過 S3 API)、MinIO 和其他 S3 相容服務。
以下設定將 EmDash 指向 S3 相容儲存桶:
import emdash, { s3 } from "emdash/astro";
export default defineConfig({
integrations: [
emdash({
storage: s3({
endpoint: process.env.S3_ENDPOINT,
bucket: process.env.S3_BUCKET,
accessKeyId: process.env.S3_ACCESS_KEY_ID,
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
region: "auto", // Optional, defaults to "auto"
publicUrl: process.env.S3_PUBLIC_URL, // Optional CDN URL
}),
}),
],
});
設定
| 選項 | 類型 | 必需 | 描述 |
|---|---|---|---|
endpoint | string | 是 | S3 端點 URL |
bucket | string | 是 | 儲存桶名稱 |
accessKeyId | string | 否* | 存取金鑰 |
secretAccessKey | string | 否* | 密鑰 |
region | string | 否 | 區域(預設:"auto") |
publicUrl | string | 否 | 選用的 CDN 或公開 URL |
* accessKeyId 和 secretAccessKey 必須一起提供,或者都省略。
從環境變數解析 S3 設定
從 s3({...}) 中省略的任何欄位都會在處理程序啟動時從相符的 S3_* 環境變數中讀取。這使您可以建置一次容器映像檔,並在啟動時注入憑證而無需重建。s3({...}) 中的明確值始終優先於環境變數。
| 環境變數 | 欄位 | 注意事項 |
|---|---|---|
S3_ENDPOINT | endpoint | 必須是有效的 http/https URL |
S3_BUCKET | bucket | |
S3_ACCESS_KEY_ID | accessKeyId | |
S3_SECRET_ACCESS_KEY | secretAccessKey | |
S3_REGION | region | 預設:"auto" |
S3_PUBLIC_URL | publicUrl | 選用的 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
將 S3 憑證與 R2 一起使用以獲得簽名上傳 URL 等功能:
storage: s3({
endpoint: "https://<account-id>.r2.cloudflarestorage.com",
bucket: "emdash-media",
accessKeyId: process.env.R2_ACCESS_KEY_ID,
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
publicUrl: "https://pub-xxxx.r2.dev",
});
在 Cloudflare 控制面板的 R2 > Manage R2 API Tokens 下產生 R2 API 憑證。
MinIO
將 S3 配接器指向帶有存取憑證的 MinIO 端點:
storage: s3({
endpoint: "https://minio.example.com",
bucket: "emdash-media",
accessKeyId: process.env.MINIO_ACCESS_KEY,
secretAccessKey: process.env.MINIO_SECRET_KEY,
publicUrl: "https://minio.example.com/emdash-media",
});
本機檔案系統
使用本機儲存進行開發。檔案儲存在磁碟上的目錄中。
import emdash, { local } from "emdash/astro";
export default defineConfig({
integrations: [
emdash({
storage: local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
}),
}),
],
});
設定
| 選項 | 類型 | 描述 |
|---|---|---|
directory | string | 檔案儲存的目錄路徑 |
baseUrl | string | 提供檔案服務的基礎 URL |
除非您設定自訂靜態檔案伺服器,否則 baseUrl 應與 EmDash 的媒體檔案端點(/_emdash/api/media/file)相符。
基於環境的設定
根據環境切換儲存後端:
import emdash, { s3, 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 binding(改用帶有 R2 憑證的 S3 配接器)
- Local
Storage 介面
所有儲存配接器實作相同的介面:
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;
}
這種一致性允許在不更改應用程式程式碼的情況下切換儲存後端。