EmDash 提供媒體庫,用於管理圖片、文件等檔案。本指南介紹上傳、整理以及在內容中使用媒體。
開啟媒體庫
在管理側欄點選 Media 即可開啟。庫中列出所有已上傳檔案,含預覽、檔名與上傳時間。
上傳檔案
在媒體庫中
-
在管理側欄點選 Media
-
點選 Upload 或將檔案拖入上傳區域
-
在電腦中選取一個或多個檔案
-
等待上傳完成
在內容編輯器中
-
在富文字編輯器中點選圖片按鈕
-
在媒體選擇器中點選 Upload
-
選取本機檔案
-
填寫替代文字後點選 Insert
支援的檔案類型
EmDash 支援常見 Web 檔案類型:
| 類別 | 副檔名 |
|---|---|
| 圖片 | .jpg, .jpeg, .png, .gif, .webp, .avif, .svg |
| 文件 | .pdf, .doc, .docx, .xls, .xlsx, .ppt, .pptx |
| 影片 | .mp4, .webm, .mov |
| 音訊 | .mp3, .wav, .ogg |
儲存後端
EmDash 支援多種儲存後端,於 Astro 設定中設定:
Local Storage
import { defineConfig } from "astro/config";
import emdash, { local } from "emdash/astro";
export default defineConfig({
integrations: [
emdash({
storage: local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
}),
}),
],
});檔案儲存在 ./uploads 目錄。適合開發與單機部署。
Cloudflare R2
import { defineConfig } from "astro/config";
import emdash, { r2 } from "emdash/astro";
export default defineConfig({
integrations: [
emdash({
storage: r2({
binding: "MEDIA_BUCKET",
publicUrl: "https://media.example.com",
}),
}),
],
});需在 wrangler.jsonc 中設定 R2 儲存貯體:
{
"r2_buckets": [
{
"binding": "MEDIA_BUCKET",
"bucket_name": "my-media-bucket",
},
],
} S3-Compatible
import { defineConfig } from "astro/config";
import emdash, { s3 } from "emdash/astro";
export default defineConfig({
integrations: [
emdash({
storage: s3({
endpoint: "https://s3.amazonaws.com",
bucket: "my-media-bucket",
accessKeyId: process.env.S3_ACCESS_KEY_ID,
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
region: "us-east-1",
publicUrl: "https://media.example.com",
}),
}),
],
});可與 Cloudflare R2(S3 API)、MinIO 及其他 S3 相容服務搭配使用。
上傳流程
EmDash 使用簽名 URL 實作安全上傳:
-
用戶端向 API 請求上傳 URL
-
伺服器產生具到期時間的簽名 URL
-
用戶端透過該 URL 直傳儲存空間
-
伺服器將檔案中繼資料寫入資料庫
大型檔案不經過應用程式伺服器,可直接上傳至雲端儲存。
整理媒體
資料夾
可建立資料夾分類:
-
在媒體庫中點選 New Folder
-
輸入資料夾名稱
-
點選 Create
-
將檔案拖入資料夾
搜尋
在搜尋框依檔名查找,支援部分相符。
篩選
可依下列條件篩選:
- Type — 圖片、文件、影片、音訊
- Date — 上傳日期範圍
- Folder — 指定資料夾
在內容中使用媒體
在富文字編輯器中
-
將游標放在要插入圖片的位置
-
點選工具列圖片按鈕
-
從媒體庫選擇或上傳新圖片
-
填寫替代文字
-
點選 Insert
作為精選圖片
-
在編輯器中開啟內容條目
-
在側欄找到 Featured Image 欄位
-
點選 Select Image
-
從媒體庫選擇或上傳
-
點選 Save
在自訂欄位中
對設定為圖片或檔案的欄位,點選欄位即可開啟媒體選擇器。
在範本中展示媒體
從內容資料讀取媒體 URL:
---
import { getEmDashEntry } from "emdash";
const { entry: post } = await getEmDashEntry("posts", Astro.params.slug);
---
{post?.data.featured_image && (
<img
src={post.data.featured_image}
alt={post.data.featured_image_alt ?? ""}
/>
)}
響應式圖片
對外部 URL 使用 Astro 的 Image 元件實作響應式圖片:
響應式圖片
對外部 URL 使用 Astro 的 Image 元件實作響應式圖片:
---
import { Image } from "astro:assets";
import { getEmDashEntry } from "emdash";
const { entry: post } = await getEmDashEntry("posts", Astro.params.slug);
---
{post?.data.featured_image && (
<Image
src={post.data.featured_image}
alt={post.data.featured_image_alt ?? ""}
width={800}
height={450}
/>
)}
刪除媒體
-
選取要刪除的檔案
-
點選 Delete
-
確認刪除
媒體 API
透過管理 API 以程式存取媒體。
上傳檔案
以 multipart/form-data 上傳:
POST /_emdash/api/media
Content-Type: multipart/form-data
Authorization: Bearer YOUR_API_TOKEN
file=<binary file data>
回應範例:
{
"success": true,
"data": {
"item": {
"id": "01ABC123",
"filename": "hero-image.jpg",
"mime_type": "image/jpeg",
"storage_key": "media/abc123/hero-image.jpg",
"width": 1200,
"height": 800
}
}
}
列出媒體
GET /_emdash/api/media?prefix=images/&limit=20
Authorization: Bearer YOUR_API_TOKEN
刪除媒體
DELETE /_emdash/api/media/images/hero.jpg
Authorization: Bearer YOUR_API_TOKEN
媒體提供者
除本機儲存外,EmDash 支援外部媒體提供者,用於專業圖片與影片代管。提供者在媒體選擇器中顯示為分頁。
可用提供者
Cloudflare Images
Cloudflare Images 提供圖片代管,支援自動最佳化、縮放與格式轉換。
import { defineConfig } from "astro/config";
import emdash from "emdash/astro";
import { cloudflareImages } from "@emdash-cms/cloudflare";
export default defineConfig({
integrations: [
emdash({
// ... database, storage config
mediaProviders: [
cloudflareImages({
accountId: import.meta.env.CF_ACCOUNT_ID,
apiToken: import.meta.env.CF_IMAGES_TOKEN,
// Optional: custom delivery domain
deliveryDomain: "images.example.com",
}),
],
}),
],
});功能:
- 在後台瀏覽並上傳圖片
- 自動最佳化與格式轉換
- 以 URL 為基礎的變換(尺寸、裁切、格式)
- 靈活的響應式變體
Cloudflare Stream
Cloudflare Stream 提供影片代管與 HLS/DASH 自適應串流。
import { defineConfig } from "astro/config";
import emdash from "emdash/astro";
import { cloudflareStream } from "@emdash-cms/cloudflare";
export default defineConfig({
integrations: [
emdash({
// ... database, storage config
mediaProviders: [
cloudflareStream({
accountId: import.meta.env.CF_ACCOUNT_ID,
apiToken: import.meta.env.CF_STREAM_TOKEN,
// Optional: player settings
controls: true,
autoplay: false,
loop: false,
}),
],
}),
],
});功能:
- 在後台瀏覽、搜尋並上傳影片
- HLS 與 DASH 自適應串流
- 自動產生縮圖
- 大型檔案直傳
多個提供者
可設定多個提供者,每個在選擇器中顯示為一個分頁:
import { defineConfig } from "astro/config";
import emdash from "emdash/astro";
import { cloudflareImages, cloudflareStream } from "@emdash-cms/cloudflare";
export default defineConfig({
integrations: [
emdash({
database: d1({ binding: "DB" }),
storage: r2({ binding: "MEDIA" }),
mediaProviders: [
cloudflareImages({
accountId: import.meta.env.CF_ACCOUNT_ID,
apiToken: import.meta.env.CF_IMAGES_TOKEN,
}),
cloudflareStream({
accountId: import.meta.env.CF_ACCOUNT_ID,
apiToken: import.meta.env.CF_STREAM_TOKEN,
}),
],
}),
],
});
本機媒體庫(「Library」分頁)始終與已設定的提供者並存。
呈現提供者媒體
使用 Image 元件呈現:
---
import { Image } from "emdash/ui";
import { getEmDashEntry } from "emdash";
const { entry: post } = await getEmDashEntry("posts", Astro.params.slug);
---
{post?.data.featured_image && (
<Image
image={post.data.featured_image}
width={800}
height={450}
/>
)}
元件會:
- 依儲存值辨識提供者
- 呈現最佳化的
<img> - 套用提供者專屬最佳化(如 Cloudflare Images 變換)
MediaValue 型別
媒體欄位儲存含提供者資訊的 MediaValue 物件:
interface MediaValue {
provider?: string; // Provider ID, defaults to "local"
id: string; // Provider-specific ID
src?: string; // Direct URL (for local media or legacy data)
previewUrl?: string; // Preview URL for admin display (external providers)
filename?: string; // Original filename
mimeType?: string; // MIME type
width?: number; // Image/video width
height?: number; // Image/video height
alt?: string; // Alt text
meta?: Record<string, unknown>; // Provider-specific metadata
}
如此無論資源代管於何處,EmDash 都能正確呈現。
下一步
- Working with Content — 在內容中使用媒體
- Create a Blog — 為文章新增圖片
- Querying Content — 在範本中展示媒體