媒體庫

本頁內容

EmDash 包含媒體庫,用於管理圖片、文件和其他檔案。本指南介紹如何上傳、整理以及在內容中使用媒體。

存取媒體庫

在管理側邊欄點擊 Media 開啟媒體庫。庫中顯示所有已上傳的檔案,包含預覽、檔案名稱和上傳日期。

EmDash 媒體庫,顯示圖片網格和上傳按鈕

上傳檔案

從媒體庫上傳

  1. 在管理側邊欄點擊 Media

  2. 點擊 Upload 或將檔案拖入上傳區域

  3. 從電腦中選擇一個或多個檔案

  4. 等待上傳完成

從內容編輯器上傳

  1. 在富文本編輯器中點擊圖片按鈕

  2. 在媒體選擇器中點擊 Upload

  3. 從電腦選擇檔案

  4. 新增替代文字後點擊 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 from "emdash/astro";
import { r2 } from "@emdash-cms/cloudflare";

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 實現安全上傳:

  1. 客戶端從 API 請求上傳 URL

  2. 伺服器生成帶過期時間的簽名 URL

  3. 客戶端使用簽名 URL 直接上傳到儲存

  4. 伺服器在資料庫中記錄檔案中繼資料

這種方式可以讓大型檔案不經過應用程式伺服器,並支援直接上傳到雲端儲存。

整理媒體

資料夾

建立資料夾來整理您的媒體:

  1. 在媒體庫中點擊 New Folder

  2. 輸入資料夾名稱

  3. 點擊 Create

  4. 將檔案拖入資料夾進行整理

搜尋

使用搜尋框按名稱尋找檔案。搜尋符合部分檔案名稱。

篩選

按以下條件篩選媒體:

  • Type - 圖片、文件、影片、音訊
  • Date - 上傳日期範圍
  • Folder - 特定資料夾

在內容中使用媒體

在富文本編輯器中

  1. 將游標放在要插入圖片的位置

  2. 點擊工具列中的圖片按鈕

  3. 從媒體庫選擇圖片或上傳新圖片

  4. 輸入替代文字

  5. 點擊 Insert

作為精選圖片

  1. 在編輯器中開啟內容項目

  2. 在側邊欄找到 Featured Image 欄位

  3. 點擊 Select Image

  4. 從媒體庫選擇或上傳

  5. 點擊 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 ?? ""}
  />
)}

回應式圖片

對於回應式圖片,使用 Astro 的 Image 元件處理外部 URL:

---
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}
  />
)}

刪除媒體

  1. 選擇要刪除的檔案

  2. 點擊 Delete

  3. 確認刪除

媒體 API

使用管理 API 以程式設計方式存取媒體。

上傳檔案

以多部分表單資料上傳媒體:

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 plain-string values)
  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 能夠正確呈現媒體,無論其託管位置如何。

下一步