介绍一下基于 PDF.js 较新版本(接近或涵盖 v5.0 概念,虽然实际稳定版本可能是 v4.x)获取批注列表的方法

首先,需要明确一点,PDF.js 的版本迭代非常快。截至目前,pdfjs-dist 的稳定版本是 v4.x 系列。虽然你提到了 v5.0,但核心 API 获取批注的方式在最近的主要版本(v3.x, v4.x)中没有发生根本性的变化。因此,之前描述的方法对于当前和近期未来的版本(很可能也包括未来的 v5.0)仍然是有效的。

核心方法依然是使用 PDFPageProxy 对象的 getAnnotations() 方法。

以下是基于当前稳定版本 (v4.x) 并适用于未来版本的中文说明:

核心方法:使用 page.getAnnotations()

这是从 PDF 文档结构中读取批注数据的标准和推荐方式。

  1. 设置和加载文档:

    • 确保你已经安装了 pdfjs-dist 包。
    • 设置 Worker 源:这是运行 PDF 解析任务所必需的。
    • 使用 pdfjsLib.getDocument() 加载 PDF 文件。
    javascript 复制代码
    import * as pdfjsLib from 'pdfjs-dist/build/pdf.mjs'; // 使用 ES 模块版本
    // 或 const pdfjsLib = require('pdfjs-dist/build/pdf.js'); // 使用 CommonJS 版本
    
    // 非常重要:设置 Worker 路径
    // 可以指向 node_modules 或你部署 worker 文件的位置
    // 例如,如果使用 Webpack 或类似工具,可以这样配置:
    // import workerSrc from 'pdfjs-dist/build/pdf.worker.mjs?url'; // Vite/Webpack 5+ URL loader
    // pdfjsLib.GlobalWorkerOptions.workerSrc = workerSrc;
    // 或者直接提供 URL 字符串:
    pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.2.67/pdf.worker.mjs'; // 使用 CDN 的例子 (版本号需匹配)
    // 或者指向你本地部署的 worker 文件
    // pdfjsLib.GlobalWorkerOptions.workerSrc = '/path/to/your/pdf.worker.mjs';
    
    const pdfPath = '你的PDF文件路径或者URL';
  2. 获取页面并调用 getAnnotations():

    • 获取 PDFDocumentProxy 对象(文档对象)。
    • 遍历文档的每一页,获取 PDFPageProxy 对象(页面对象)。
    • 对每个页面对象调用 page.getAnnotations() 方法。这是一个异步方法,返回一个 Promise,该 Promise 解析为一个包含该页面所有批注数据的对象数组。
    javascript 复制代码
    async function getAllAnnotations(pdfPath) {
      const loadingTask = pdfjsLib.getDocument(pdfPath);
      try {
        const pdfDocument = await loadingTask.promise;
        console.log(`PDF 文档加载成功,总页数: ${pdfDocument.numPages}`);
    
        const allAnnotationsData = []; // 存储所有批注数据
    
        for (let i = 1; i <= pdfDocument.numPages; i++) {
          const page = await pdfDocument.getPage(i);
          console.log(`正在处理第 ${i} 页...`);
    
          // 获取当前页面的批注数据数组
          const annotations = await page.getAnnotations();
    
          if (annotations.length > 0) {
            console.log(`第 ${i} 页找到 ${annotations.length} 个批注。`);
            // 为每个批注添加页码信息,方便后续使用
            const annotationsWithPageNum = annotations.map(anno => ({
              ...anno, // 复制原始批注数据
              pageNumber: i // 添加页码字段
            }));
            allAnnotationsData.push(...annotationsWithPageNum);
          } else {
             console.log(`第 ${i} 页没有批注。`);
          }
          // 注意:在 v4.x 及以后版本,不再需要手动调用 page.cleanup(),
          // PDF.js 内部会更好地管理内存。
        }
    
        console.log(`\n文档中总共获取到 ${allAnnotationsData.length} 个批注。`);
        return allAnnotationsData;
    
      } catch (error) {
        console.error('加载或处理 PDF 时出错:', error);
        throw error; // 或者返回空数组 []
      }
    }
    
    // --- 如何使用 ---
    getAllAnnotations(pdfPath)
      .then(annotations => {
        console.log('\n--- 所有批注的详细数据 ---');
        annotations.forEach((anno, index) => {
          console.log(
            `${index + 1}: 页码=${anno.pageNumber}, ` +
            `类型=${anno.subtype}, ` +
            `ID=${anno.id}, ` + // 批注 ID
            `矩形区域=[${anno.rect}], ` +
            `内容=${anno.contents || '无'}` // 显示文本内容(如果有)
          );
          // 你可以根据 anno.subtype (类型) 来访问不同的特定属性
          // 例如,对于 'Link' 类型,可能有 anno.url
          // 对于 'Highlight', 'Underline' 等,可能有 anno.quadPoints
        });
      })
      .catch(err => {
        console.error('获取批注失败:', err);
      });

要点总结 (适用于 v4.x 及以后版本):

  1. API 稳定性 : page.getAnnotations() 是获取批注的核心且稳定的 API,在 v4.x 中依然如此,预计在 v5.0 中也不会改变。
  2. 异步操作 : 记住 getDocument()getPage()getAnnotations() 都是异步的,需要使用 async/await.then() 处理 Promise。
  3. 返回数据 : getAnnotations() 返回的是原始的 JavaScript 对象数组 ,每个对象代表一个批注,其属性直接对应 PDF 规范中定义的批注字典字段(如 subtype, rect, contents, color, id, modificationDate 等)。它返回的不是 HTML 元素
  4. Worker 配置 : 正确设置 GlobalWorkerOptions.workerSrc 是 PDF.js 运行的前提,尤其是在浏览器环境或 Node.js 中。确保 worker 文件的版本与你使用的 pdfjs-dist 版本匹配。
  5. 批注类型 : 返回的批注数据结构会根据批注的 subtype (类型,如 'Text', 'Link', 'Highlight', 'Square', 'Ink' 等) 而有所不同,包含各自特定的属性。你需要查阅 PDF 规范或 PDF.js 文档来了解不同类型批注的具体属性。
  6. 内存管理 : 较新版本的 PDF.js (v3.x 之后) 改进了内存管理,通常不再需要像旧版本那样显式调用 page.cleanup(),尤其是在只获取批注数据时。

如果你在使用 PDF.js 预构建的查看器 (Viewer):

获取批注的方式与之前描述的类似,你需要先获取到查看器实例 (PDFViewerApplication),然后通过 PDFViewerApplication.pdfDocument 拿到 PDFDocumentProxy 对象,接下来的步骤就和上面的核心方法一样了。

javascript 复制代码
// 在查看器环境的控制台或脚本中运行
async function getAnnotationsFromViewer() {
  if (typeof PDFViewerApplication === 'undefined' || !PDFViewerApplication.pdfDocument) {
    console.error('PDFViewerApplication 或其 pdfDocument 尚未准备好。');
    return;
  }
  const pdfDocument = PDFViewerApplication.pdfDocument;
  // ... 接下来的逻辑和上面的 getAllAnnotations 函数内部类似 ...
  // 遍历 pdfDocument.numPages, 调用 pdfDocument.getPage(i), 然后 page.getAnnotations()
  // ...
}

总之,获取 PDF 批注列表的核心方法 page.getAnnotations() 在 PDF.js v4.x(以及可预见的未来版本)中保持稳定和有效。关键在于正确设置环境、处理异步操作并理解返回的数据结构。

相关推荐
拉不动的猪几秒前
设计模式之------策略模式
前端·javascript·面试
旭久1 分钟前
react+Tesseract.js实现前端拍照获取/选择文件等文字识别OCR
前端·javascript·react.js
独行soc11 分钟前
2025年常见渗透测试面试题-红队面试宝典下(题目+回答)
linux·运维·服务器·前端·面试·职场和发展·csrf
uhakadotcom26 分钟前
Google Earth Engine 机器学习入门:基础知识与实用示例详解
前端·javascript·面试
麓殇⊙42 分钟前
Vue--组件练习案例
前端·javascript·vue.js
outstanding木槿1 小时前
React中 点击事件写法 的注意(this、箭头函数)
前端·javascript·react.js
会点php的前端小渣渣1 小时前
vue的计算属性computed的原理和监听属性watch的原理(新)
前端·javascript·vue.js
_一条咸鱼_2 小时前
深入解析 Vue API 模块原理:从基础到源码的全方位探究(八)
前端·javascript·面试
患得患失9492 小时前
【前端】【难点】前端富文本开发的核心难点总结与思路优化
前端·富文本
执键行天涯2 小时前
在vue项目中package.json中的scripts 中 dev:“xxx“中的xxx什么概念
前端·vue.js·json