媒体库

本页内容

EmDash 包含一个用于管理图片、文档和其他文件的媒体库。本指南涵盖在内容中上传、组织和使用媒体。

访问媒体库

通过管理侧边栏点击 Media 打开媒体库。媒体库显示所有已上传的文件,包括预览、文件名和上传日期。

EmDash 媒体库显示带有上传按钮的图片网格

上传文件

从媒体库上传

  1. 点击管理侧边栏中的 Media

  2. 点击 Upload 或将文件拖拽到上传区域

  3. 从计算机中选择一个或多个文件

  4. 等待上传完成

从内容编辑器上传

  1. 在富文本编辑器中,点击图片按钮

  2. 在媒体选择器中点击 Upload

  3. 从计算机中选择文件

  4. 添加替代文本并点击 插入

支持的文件类型

EmDash 支持常见的 Web 文件类型:

类别扩展名
图片.jpg, .jpeg, .png, .gif, .webp, .avif, .svg
文档.pdf, .doc, .docx, .xls, .xlsx, .ppt, .pptx
视频.mp4, .webm, .mov
音频.mp3, .wav, .ogg

存储后端

EmDash 支持多种存储后端。在 Astro 配置中设置存储:

本地存储

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 兼容

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. 点击 创建

  4. 将文件拖入文件夹进行组织

搜索

使用搜索框按名称查找文件。搜索可匹配部分文件名。

筛选

按以下条件筛选媒体:

  • 类型 - 图片、文档、视频、音频
  • 日期 - 上传日期范围
  • 文件夹 - 特定文件夹

在内容中使用媒体

在富文本编辑器中

  1. 将光标放在您要插入图片的位置

  2. 点击工具栏中的图片按钮

  3. 从媒体库选择图片或上传新图片

  4. 输入替代文本

  5. 点击 插入

作为特色图片

  1. 在编辑器中打开内容条目

  2. 在侧边栏找到 Featured Image 字段

  3. 点击 选择图片

  4. 从媒体库选择或上传

  5. 点击 保存

在自定义字段中

对于配置为图片或文件类型的字段,点击该字段打开媒体选择器。

在模板中显示媒体

从内容数据中访问媒体 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 ?? ""}
  />
)}

响应式图片

对于 EmDash 媒体字段,使用 emdash/ui 中的 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}
    priority
  />
)}

priority 用于首屏主图片。它设置 loading="eager"fetchpriority="high"loading 控制是否延迟加载,fetchpriority 给浏览器提供请求优先级提示。

删除媒体

  1. 选择要删除的文件

  2. 点击 删除

  3. 确认删除

媒体 API

通过管理 API 以编程方式访问媒体。

上传文件

以 multipart 表单数据形式上传媒体:

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({
      // ... 数据库、存储配置
      mediaProviders: [
        cloudflareImages({
          accountId: import.meta.env.CF_ACCOUNT_ID,
          apiToken: import.meta.env.CF_IMAGES_TOKEN,
          // 可选:自定义分发域名
          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({
      // ... 数据库、存储配置
      mediaProviders: [
        cloudflareStream({
          accountId: import.meta.env.CF_ACCOUNT_ID,
          apiToken: import.meta.env.CF_STREAM_TOKEN,
          // 可选:播放器设置
          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;    // 提供商 ID,默认为 "local"
  id: string;           // 提供商特定的 ID
  src?: string;         // 直接 URL(用于本地媒体或纯字符串值)
  previewUrl?: string;  // 管理面板显示的预览 URL(外部提供商)
  filename?: string;    // 原始文件名
  mimeType?: string;    // MIME 类型
  width?: number;       // 图片/视频宽度
  height?: number;      // 图片/视频高度
  alt?: string;         // 替代文本
  meta?: Record<string, unknown>; // 提供商特定的元数据
}

这使 EmDash 能够正确渲染媒体,无论其托管在何处。

下一步