媒体库

本页内容

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 能够正确渲染媒体,无论其托管位置如何。

下一步