---
title: "从编辑器导出 PDF"
description: "了解如何在我们的文档中使用 Export PDF 扩展将 Tiptap 编辑器内容导出为 PDF 文件。"
canonical_url: "https://tiptap.zhcndoc.com/conversion/export/pdf/editor-extension"
---

# 从编辑器导出 PDF

了解如何在我们的文档中使用 Export PDF 扩展将 Tiptap 编辑器内容导出为 PDF 文件。

- **1. 激活试用或订阅**

  在你的账户中开始 [免费试用](https://cloud.tiptap.dev/v2?trial=true) 或 [订阅 Start
  方案](https://cloud.tiptap.dev/v2/billing)。
- **2. 从私有仓库安装**

  要安装这些前端扩展，请按照 [设置指南](https://tiptap.zhcndoc.com/guides/pro-extensions.md) 对 Tiptap 的私有 npm 仓库进行身份验证。

> **Interactive demo:** [ExportPdf](https://embed-pro.tiptap.dev/preview/Extensions/ExportPdf)

使用 Tiptap 的 `@tiptap-pro/extension-export-pdf` 将编辑器内容导出为 `.pdf` 文件。此扩展通过将文档发送到 Tiptap 转换服务进行转换，把 PDF 导出功能集成到你的编辑器中。

如果你更希望在自己的端处理转换，也可以改用 [REST API](https://tiptap.zhcndoc.com/conversion/export/pdf/rest-api.md)。

## 安装 PDF 导出扩展

Conversion 扩展发布在 Tiptap 的私有 npm 仓库中。请按照 [私有仓库指南](https://tiptap.zhcndoc.com/guides/pro-extensions.md) 集成这些扩展。

完成后，你就可以安装并导入 **Export PDF** 扩展包。

```bash
npm i @tiptap-pro/extension-export-pdf
```

```js
import { ExportPdf } from '@tiptap-pro/extension-export-pdf'
```

## 配置扩展

`ExportPdf` 扩展可以使用 `ExportPdfOptions`（`object`）作为 `configure` 方法的参数进行配置，包含以下属性：

```ts
import { ExportPdf } from '@tiptap-pro/extension-export-pdf'

const editor = new Editor({
  extensions: [
    // 其他扩展 ...
    ExportPdf.configure({
      endpoint: 'https://api.tiptap.dev/v2/convert',
      token: 'YOUR_TOKEN',
      styleOverrides: {},
      headers: {},
      footers: {},
      pageSize: { width: '21cm', height: '29.7cm' },
      pageMargins: { top: '1cm', bottom: '1cm', left: '1cm', right: '1cm' },
      customNodes: [],
      onCompleteExport: (result) => {
        // 处理导出的 Blob
      },
    }),
    // 其他扩展 ...
  ],
})
```

| 参数                 | 类型                       | 描述                                                                             | 默认值                                   |
| ------------------ | ------------------------ | ------------------------------------------------------------------------------ | ------------------------------------- |
| `endpoint`         | `string`                 | 用于转换的 Tiptap API 端点                                                            | `'https://api.tiptap.dev/v2/convert'` |
| `token`            | `string`                 | 用于身份验证的 Tiptap JWT                                                             | `''`                                  |
| `styleOverrides`   | `Record<string, string>` | 要应用于导出的样式覆盖                                                                    | `undefined`                           |
| `headers`          | `HeaderConfig`           | 导出文档的页眉配置                                                                      | `undefined`                           |
| `footers`          | `FooterConfig`           | 导出文档的页脚配置                                                                      | `undefined`                           |
| `pageSize`         | `PageSize`               | 页面大小配置                                                                         | `undefined`                           |
| `pageMargins`      | `PageMargins`            | 页面边距配置                                                                         | `undefined`                           |
| `customNodes`      | `CustomNodeDefinition[]` | 用于基于 DOCX 的转换的自定义节点定义（需要 `@tiptap-pro/extension-export-docx`）                  | `undefined`                           |
| `customFonts`      | `CustomFont[]`           | 为 PDF 导出提供的自定义字体文件（仅限本地部署）                                                     | `undefined`                           |
| `onCompleteExport` | `(result: Blob) => void` | 接收导出文件 Blob 的回调                                                                | 如果未提供则抛出错误                            |
| `onExportError`    | `(error: Error) => void` | 可选回调；当导出流程被拒绝时触发（动态导入失败、DOCX 转换失败、网络错误、非 OK 响应）。未提供时，错误会通过 `console.error` 记录。 | `undefined`                           |

### 页眉和页脚插槽值

每个页眉和页脚插槽（`default`、`first`、`even`）都接受五种形态中的任意一种；请选择与你的数据相匹配的形式。前三种仅使用 `@tiptap-pro/extension-export-pdf` 即可；后两种还需要安装 `@tiptap-pro/extension-export-docx`（它们会走先 DOCX 后 PDF 的导出路径，并且采用懒加载，因此不会影响仅使用 PDF 的消费者）。

| 形态                            | 示例                                         | 说明                                                          |
| ----------------------------- | ------------------------------------------ | ----------------------------------------------------------- |
| 纯文本                           | `'Company name, 2026'`                     | 无样式的页眉/页脚。                                                  |
| 字符串化的 Tiptap JSONContent      | `JSON.stringify(myHeaderDoc)`              | 预先序列化的 Tiptap 节点。保留富文本格式。                                   |
| Tiptap JSONContent 对象         | `{ type: 'doc', content: [/* … */] }`      | 直接传入富文本 Tiptap 节点。无需字符串化。                                   |
| `docx` `Header` / `Footer` 实例 | `new Docx.Header({ children: [/* … */] })` | 完整的 DOCX 级别控制。需要 DOCX 扩展。                                   |
| 返回 `Header` / `Footer` 的异步工厂  | `() => convertHeader({ node })`            | 在导出时按需构建。典型用法：`convertHeader` / `convertFooter`。需要 DOCX 扩展。 |

Tiptap JSONContent 对象**必须**包含 `type` 字段。扩展在运行时就是通过这个字段区分 Tiptap 节点和 `docx` 实例的。不包含 `type` 且也不是 `Header` / `Footer` 实例的对象会被丢弃，并通过 `console.warn` 提示出问题的值，不会传递给 DOCX 序列化器。

在 TypeScript 中，这些形态会收敛为两个别名（`type` 要求被编码在 `TiptapNodeContent` 中）：

```ts
import type { JSONContent } from '@tiptap/core'
import type { Footer, Header } from 'docx'

type TiptapNodeContent = JSONContent & { type: string }

type HeaderSlotValue = string | TiptapNodeContent | Header | (() => Promise<Header>)
type FooterSlotValue = string | TiptapNodeContent | Footer | (() => Promise<Footer>)
```

### HeaderConfig

| 属性                   | 类型                | 描述                                                      |
| -------------------- | ----------------- | ------------------------------------------------------- |
| `evenAndOddHeaders`  | `boolean`         | 是否为奇数页和偶数页使用不同的页眉。                                      |
| `differentFirstPage` | `boolean`         | 是否为第一页使用不同的页眉。当为 `true` 时，第一页使用 `first` 值而不是 `default`。 |
| `default`            | `HeaderSlotValue` | 每一页的标准默认页眉；如果启用 `evenAndOddHeaders`，则为奇数页页眉。            |
| `first`              | `HeaderSlotValue` | 第一页的页眉。仅在 `differentFirstPage` 为 `true` 时使用。            |
| `even`               | `HeaderSlotValue` | 偶数页的页眉。仅在 `evenAndOddHeaders` 为 `true` 时使用。             |

### FooterConfig

| 属性                   | 类型                | 描述                                                      |
| -------------------- | ----------------- | ------------------------------------------------------- |
| `evenAndOddFooters`  | `boolean`         | 是否为奇数页和偶数页使用不同的页脚。                                      |
| `differentFirstPage` | `boolean`         | 是否为第一页使用不同的页脚。当为 `true` 时，第一页使用 `first` 值而不是 `default`。 |
| `default`            | `FooterSlotValue` | 每一页的标准默认页脚；如果启用 `evenAndOddFooters`，则为奇数页页脚。            |
| `first`              | `FooterSlotValue` | 第一页的页脚。仅在 `differentFirstPage` 为 `true` 时使用。            |
| `even`               | `FooterSlotValue` | 偶数页的页脚。仅在 `evenAndOddFooters` 为 `true` 时使用。             |

### PageSize

| 属性       | 类型       | 描述                                      | 默认值        |
| -------- | -------- | --------------------------------------- | ---------- |
| `width`  | `string` | 页面宽度。必须是一个正数，后跟有效单位（cm、in、pt、pc、mm、px）。 | `"21cm"`   |
| `height` | `string` | 页面高度。必须是一个正数，后跟有效单位（cm、in、pt、pc、mm、px）。 | `"29.7cm"` |

### PageMargins

| 属性       | 类型       | 描述                                             | 默认值     |
| -------- | -------- | ---------------------------------------------- | ------- |
| `top`    | `string` | 页面上边距。可以为负值。必须是一个数字，后跟有效单位（cm、in、pt、pc、mm、px）。 | `"1cm"` |
| `bottom` | `string` | 页面下边距。可以为负值。必须是一个数字，后跟有效单位（cm、in、pt、pc、mm、px）。 | `"1cm"` |
| `left`   | `string` | 页面左边距。必须是一个正数，后跟有效单位（cm、in、pt、pc、mm、px）。       | `"1cm"` |
| `right`  | `string` | 页面右边距。必须是一个正数，后跟有效单位（cm、in、pt、pc、mm、px）。       | `"1cm"` |

### CustomFont

> **仅限本地部署:**
>
> 自定义字体仅可用于本地部署。如果你有兴趣在 Tiptap 的云服务中使用自定义
> 字体，请 [联系我们了解 Enterprise
> 方案](https://tiptap.dev/pricing)。

| 属性           | 类型       | 描述                                     |
| ------------ | -------- | -------------------------------------- |
| `url`        | `string` | 直接指向 `.ttf` 或 `.woff2` 字体文件的 HTTPS URL |
| `fontFamily` | `string` | 文档中使用的字体族名称                            |

## 导出 PDF 文件

安装该扩展后，你可以使用 `exportPdf` 命令将编辑器内容导出为 `.pdf`。

```ts
/**
 * 通过 Tiptap 转换服务将当前文档导出为 PDF 文件。
 *
 * @param options - 所有扩展级选项都可以在单次调用时被覆盖
 * @example editor.commands.exportPdf({ onCompleteExport: (result) => {} })
 */
exportPdf: (options?: ExportPdfCommandOptions) => ReturnType
```

`ExportPdfCommandOptions` 接口继承自 `ExportPdfOptions`，因此每个配置项都可以在每次命令调用时被覆盖：

| Property           | Type                     | Description           |
| ------------------ | ------------------------ | --------------------- |
| `endpoint`         | `string`                 | 覆盖此特定导出的 API 端点       |
| `token`            | `string`                 | 覆盖此特定导出的 JWT 令牌       |
| `styleOverrides`   | `Record<string, string>` | 覆盖此特定导出的样式覆盖项         |
| `headers`          | `HeaderConfig`           | 覆盖此特定导出的页眉配置          |
| `footers`          | `FooterConfig`           | 覆盖此特定导出的页脚配置          |
| `pageSize`         | `PageSize`               | 覆盖此特定导出的页面尺寸          |
| `pageMargins`      | `PageMargins`            | 覆盖此特定导出的页面边距          |
| `customNodes`      | `CustomNodeDefinition[]` | 覆盖此特定导出的自定义节点定义       |
| `customFonts`      | `CustomFont[]`           | 覆盖此特定导出的自定义字体（仅限本地部署） |
| `onCompleteExport` | `(result: Blob) => void` | 覆盖此特定导出的回调            |
| `onExportError`    | `(error: Error) => void` | 覆盖此特定导出的错误处理器         |

```js
import { ExportPdf } from '@tiptap-pro/extension-export-pdf'

const editor = new Editor({
  extensions: [
    // 其他扩展 ...
    ExportPdf.configure({
      token: 'YOUR_TOKEN',
      onCompleteExport(result) {
        // 下载 PDF 文件
        const url = URL.createObjectURL(result)
        const a = document.createElement('a')

        a.href = url
        a.download = 'document.pdf'
        a.click()

        URL.revokeObjectURL(url)
      },
    }),
    // 其他扩展 ...
  ],
})

// 使用扩展级回调
editor.chain().exportPdf().run()

// 或为特定导出覆盖选项
editor
  .chain()
  .exportPdf({
    pageSize: { width: '8.5in', height: '11in' },
    onCompleteExport(result) {
      // 为此次特定导出进行自定义处理
      const url = URL.createObjectURL(result)
      window.open(url)
    },
  })
  .run()
```

### 工作原理

当你调用 `exportPdf` 时，扩展会将编辑器文档序列化为 JSON，并连同任何已配置的选项（样式覆盖、页面布局、页眉、页脚、自定义字体）一起发送到 Tiptap 转换服务。该服务会将文档转换为 PDF，并以二进制 blob 的形式返回。`onCompleteExport` 回调会直接接收这个 blob，你可以随后按需下载或处理它。错误会作为异常抛出，而不是通过回调传递。

## 自定义字体

> **仅限本地部署:**
>
> 自定义字体仅适用于本地部署。如果你有兴趣在 Tiptap 的云服务中使用自定义
> 字体，请[联系我们了解 Enterprise
> 方案](https://tiptap.dev/pricing)。

PDF 导出支持本地部署中的自定义字体。你可以通过提供一组字体 URL 来配置自定义字体，转换服务会下载这些字体并在生成 PDF 时使用它们。

字体文件必须是 `.ttf` 或 `.woff2` 格式，并且可通过 HTTPS 访问。`fontFamily` 必须与文档文本样式中使用的字体族名称一致。

```ts
ExportPdf.configure({
  token: 'YOUR_TOKEN',
  customFonts: [
    {
      url: 'https://your-cdn.com/fonts/CustomFont-Regular.ttf',
      fontFamily: 'Custom Font',
    },
    {
      url: 'https://your-cdn.com/fonts/CustomFont-Bold.ttf',
      fontFamily: 'Custom Font',
    },
  ],
  onCompleteExport(result) {
    // 处理导出的 PDF
  },
})
```

你也可以在命令调用时覆盖自定义字体：

```ts
editor
  .chain()
  .exportPdf({
    customFonts: [
      {
        url: 'https://your-cdn.com/fonts/SpecialFont.woff2',
        fontFamily: 'Special Font',
      },
    ],
  })
  .run()
```

## 预期结果

- **需要身份验证。** 导出会将文档发送到 Convert 服务，该服务需要携带 `aud: "Convert"` 的签名令牌（`token`）。请在你的服务器上签发令牌，切勿在浏览器中暴露签名密钥。参见 [身份验证](https://tiptap.zhcndoc.com/authentication.md)。
- **你可能需要处理的 HTTP 响应：** `401`（缺少或无效的 JWT）、`403`（该操作不允许你的应用使用——最常见的是你的套餐不包含某种格式，或在云计划下使用 `customFonts`）、`5xx`（临时性的服务端错误；请使用退避重试）。
- **自定义字体是 Enterprise / 本地部署功能。** 在云计划中，携带 `customFonts` 的请求会返回 `403`。如需启用，请联系我们了解 [Enterprise plan](https://tiptap.dev/pricing) 或运行本地部署。
- **每个请求都会在响应前端到端处理完毕。** 非常大的文档可能需要更长时间才能返回；请相应地设置你这边的请求超时时间。

## 不要预期

- **从 DOCX → PDF 的往返完全一致。** PDF 是固定布局格式；Word 和 Convert 服务使用不同的布局引擎，因此视觉输出可能会与 Word 的 PDF 打印在细微之处有所不同。
- \*\*复杂布局与 Word 像素级完全一致，\*\*尤其是多栏分节、从右到左文本，或依赖 Word 特定布局怪癖的内容。
- **在生成的 PDF 中进行编辑。** PDF 导出是单向的。若要保留可编辑性，也请导出为 DOCX。

## 支持与限制

| **功能**              | **支持**                      |
| ------------------- | --------------------------- |
| **文本内容**            | ✓ 基本文本、间距、标点                |
| **文本格式**            | ✓ 加粗、斜体、下划线、删除线、对齐、行高       |
| **块级元素**            | ✓ 段落、标题（1–6）、引用块、有序列表和无序列表  |
| **表格**              | ✓ 基本结构、表头行、colspan          |
| **链接**              | ✓ 超链接                       |
| **媒体（图片）**          | ✓ 嵌入图片，保留尺寸                 |
| **样式**              | ✓ 字体族\*、字体颜色、字体大小、背景颜色、行高   |
| **自定义字体**           | ✓ 仅限本地部署（`.ttf` 和 `.woff2`） |
| **页眉和页脚**           | ✓                           |
| **数学公式**            | ✓                           |
| **分页符**             | ✓                           |
| **分节**              | ✗                           |
| **脚注和尾注**           | ✗                           |
| **评论和修订**           | ✗                           |
| **目录**              | ✗                           |
| **高级格式**            | ✗ 栏、文字方向、表单、宏、嵌入式脚本         |
| **元数据**             | ✗                           |
| **文本框、形状、SmartArt** | ✗                           |

- 当使用 Google 字体（自动可用）或通过 `customFonts` 选项配置的自定义字体（仅限本地部署）时，支持字体族。

如需查看按功能细分的详细说明，请参阅 [支持的功能](https://tiptap.zhcndoc.com/conversion/getting-started/feature-support-matrix.md) 矩阵。请注意，[DOCX 导出扩展](https://tiptap.zhcndoc.com/conversion/export/docx/editor-extension.md) 中可用的元素覆盖（`paragraphOverrides`、`textRunOverrides`、`tableOverrides`、`tableCellOverrides`、`imageOverrides`）不会传递到 PDF 转换中。
