3 min read

解决 Node.js 中 pdf.js DOMMatrix is not defined 错误

问题背景

在使用 Node.js 环境下运行 pdf.js 时,经常会遇到 DOMMatrix is not defined 的错误。这是因为 DOMMatrix 是浏览器环境中的 Web API,在 Node.js 环境中默认是不存在的。

错误表现

当你在 Node.js 中使用 pdf.js 处理 PDF 文件时,可能会看到如下错误信息:

ReferenceError: DOMMatrix is not defined

错误原因

DOMMatrix 是一个用于表示和操作 4x4 矩阵的 Web API,主要用于 2D 和 3D 转换。它在浏览器环境中是内置的,但在 Node.js 环境中并不存在。pdf.js 在处理 PDF 文件时需要使用 DOMMatrix 进行坐标转换和矩阵运算,因此在没有 DOMMatrix 的环境中就会报错。

解决方案

要解决这个问题,我们需要在 Node.js 环境中提供一个 DOMMatrix 的实现。推荐使用 @napi-rs/canvas 包,它提供了一个高性能的 DOMMatrix 实现。

步骤一:安装依赖

首先安装 @napi-rs/canvas 包:

npm install @napi-rs/canvas

步骤二:添加 DOMMatrix 定义

在你的代码中,在引入 pdf.js 之前添加以下代码:

import { DOMMatrix } from '@napi-rs/canvas';

if (typeof global.DOMMatrix === 'undefined') {
  // @ts-ignore
  global.DOMMatrix = DOMMatrix;
}

代码解释

  • 导入 DOMMatrix:从 @napi-rs/canvas 包中导入 DOMMatrix 类
  • 全局检查:检查全局对象中是否已经定义了 DOMMatrix
  • 全局赋值:如果没有定义,将导入的 DOMMatrix 赋值给 global.DOMMatrix
  • TypeScript 忽略:使用 @ts-ignore 注释避免 TypeScript 类型检查报错

完整示例

以下是一个完整的使用示例:

// 首先设置 DOMMatrix
import { DOMMatrix } from '@napi-rs/canvas';

if (typeof global.DOMMatrix === 'undefined') {
  // @ts-ignore
  global.DOMMatrix = DOMMatrix;
}

// 然后引入和使用 pdf.js
import * as pdfjsLib from 'pdfjs-dist';

// 设置 pdf.js worker
pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs-dist/build/pdf.worker.js';

async function readPdf(pdfData) {
  const loadingTask = pdfjsLib.getDocument({data: pdfData});
  const pdf = await loadingTask.promise;
  
  // 获取第一页
  const page = await pdf.getPage(1);
  
  // 获取文本内容
  const textContent = await page.getTextContent();
  
  return textContent;
}

export { readPdf };

注意事项

  1. 顺序重要:确保在引入 pdf.js 之前定义 DOMMatrix
  2. Node.js 版本@napi-rs/canvas 需要 Node.js 14 或更高版本
  3. 系统依赖:在某些系统上可能需要安装额外的图形库依赖
  4. 性能考虑@napi-rs/canvas 提供了原生性能,适合生产环境使用

替代方案

除了使用 @napi-rs/canvas,还有其他一些替代方案:

  • canvas:较老的 canvas 实现,性能相对较低
  • 自定义实现:可以自己实现一个简单的 DOMMatrix 类
  • jsdom:引入完整的 DOM 环境,但较重

总结

通过使用 @napi-rs/canvas 包并在全局定义 DOMMatrix,可以有效解决 Node.js 环境中 pdf.js 的 DOMMatrix 未定义问题。这种方法简单高效,并且提供了良好的性能表现,是目前推荐的解决方案。

记住,在处理任何需要在 Node.js 中使用浏览器特有 API 的情况时,都可以考虑类似的解决方案:找到合适的 Node.js 实现,并在全局范围内定义它。