使用 pdf.js 在 Node.js 中将 PDF 首页转换为 PNG 图片:pdf2png 示例实战指南

发布时间:2026/9/18 1:36:13

使用 pdf.js 在 Node.js 中将 PDF 首页转换为 PNG 图片:pdf2png 示例实战指南 使用 pdf.js 在 Node.js 中将 PDF 首页转换为 PNG 图片pdf2png 示例实战指南【免费下载链接】pdf.jsPDF Reader in JavaScript项目地址: https://gitcode.com/gh_mirrors/pd/pdf.js导读本文基于 pdf.js 仓库中的官方 Node.js 示例 examples/node/pdf2png/README.md 及其核心实现 pdf2png.mjs完整讲解如何在纯 Node.js 环境下加载 PDF 文档、渲染页面到 Canvas并输出为 PNG 图片文件。读完本文你将掌握 pdf.js 在服务端无浏览器 DOM环境下的完整工作链路从gulp dist-install构建本地 npm 包到getDocument加载文档、page.getViewport计算视口、canvasFactory创建画布、page.render绘制页面最后用canvas.toBuffer(image/png)落盘成图。一、示例概览它解决什么问题pdf2png是 pdf.js 提供的官方示例之一其 README 开篇即说明目标Example to demonstrate converting a PDF file to a PNG image using the PDF.js library.即演示如何使用 pdf.js 库把 PDF 文件转换为 PNG 图片。具体而言该示例会从命令行参数或默认路径读取一个 PDF 文件加载文档并取出第一页以 100% 缩放比例在 Node 侧的 Canvas 上渲染该页将画布内容编码为 PNG 二进制数据并写入output.png释放页面资源page.cleanup()。与仓库中其他 Node 示例形成互补同目录下的 getinfo.mjs 演示元数据与文本内容抽取examples/text-only/pdf2svg.mjs 演示在浏览器端把文本内容转成 SVG而pdf2png则聚焦于像素级栅格化输出是服务端截图、预览图生成、文档转图片等场景的最小可运行模板。二、运行环境与前置准备2.1 环境要求从仓库根目录 package.json 可以确认本项目为 ES Moduletype: module且 Node.js 引擎要求为22.13.0 || 24。因此运行示例前请确保Node.js 版本 ≥ 22.13.0或 ≥ 24已安装项目依赖npm 会自动安装pdfjs-dist、gulp 等已构建 pdf.js 发行包。2.2 安装依赖并构建 pdf.js 库README 给出了两条初始化命令$ npm install $ gulp dist-installnpm install安装仓库根目录的依赖包括 gulp 构建工具链与运行时所需的pdfjs-dist等 npm 包。gulp dist-install这是 pdf.js 仓库的**自举bootstrap**步骤。查看 gulpfile.mjs 中dist-install任务的定义gulpfile.mjs 第 3493–3502 行附近可以看到dist-install, gulp.series(dist, function createDistInstall(done) { let distPath DIST_DIR; // 计算相对路径后…… safeSpawnSync(npm, [install, distPath], opts);它先执行dist任务构建build/dist/目录下的 pdf.js 发行产物包括pdf.mjs、pdf.worker.mjs、cmaps/、standard_fonts/等资源再把构建结果作为一个本地 npm 包安装到项目的node_modules中。这一步是示例代码中import { getDocument } from pdfjs-dist/legacy/build/pdf.mjs能够解析的前提务必在运行示例前完成。三、运行示例把 PDF 第一页转成 PNGREADME 给出运行命令$ cd examples/node/pdf2png $ node pdf2png.mjs执行后会在当前目录examples/node/pdf2png/生成output.png控制台输出类似# PDF document loaded. Finished converting first page of PDF file to a PNG image.3.1 如何指定自己的 PDF 文件示例实现 pdf2png.mjs 支持把目标 PDF 路径作为第一个命令行参数传入第 28–29 行const pdfPath process.argv[2] || ../../../web/compressed.tracemonkey-pldi-09.pdf;因此可以这样转换任意本地 PDF$ node pdf2png.mjs /path/to/your/document.pdf若不传参数则默认使用仓库自带的 web/compressed.tracemonkey-pldi-09.pdfpdf.js 官方示例常用的测试文档文件内容以Uint8Array形式读入内存const data new Uint8Array(fs.readFileSync(pdfPath));四、源码逐段精讲pdf2png.mjs 的完整工作流下面按 pdf2png.mjs 的执行顺序拆解每一段代码的作用。4.1 导入与资源路径配置import fs from fs; import { getDocument } from pdfjs-dist/legacy/build/pdf.mjs; // Some PDFs need external cmaps. const CMAP_URL ../../../node_modules/pdfjs-dist/cmaps/; const CMAP_PACKED true; // Where the standard fonts are located. const STANDARD_FONT_DATA_URL ../../../node_modules/pdfjs-dist/standard_fonts/;几个要点导入的是pdfjs-dist/legacy/build/pdf.mjs即legacy 构建它不依赖现代浏览器私有特性更适合 Node.js 服务端环境cMapUrl部分 PDF 使用 CJK 等编码需要外部字符映射表cmap。该路径指向gulp dist-install安装到node_modules的pdfjs-dist/cmaps/目录cMapPacked: true告知 pdf.js 使用.bcmap压缩格式的 cmap 文件仓库 external/bcmaps 中即存放这些.bcmap资源standardFontDataUrl指向标准 14 字体数据如 external/standard_fonts 中的 Foxit/Liberation 字体用于 PDF 内置标准字体的替换渲染。4.2 加载文档getDocumentconst loadingTask getDocument({ data, cMapUrl: CMAP_URL, cMapPacked: CMAP_PACKED, standardFontDataUrl: STANDARD_FONT_DATA_URL, }); try { const pdfDocument await loadingTask.promise; console.log(# PDF document loaded.);getDocument返回一个loadingTask其.promise在文档解析完成后 resolve 为PDFDocumentProxy这里以内存data字节流方式加载同样的 API 也支持{ url }方式参见 getinfo.mjs 中的getDocument({ url: pdfPath })cmap 与标准字体配置属于可选项但强烈建议缺少时中文等复杂编码 PDF 可能渲染出乱码或空白。4.3 获取页面与视口viewportconst page await pdfDocument.getPage(1); const viewport page.getViewport({ scale: 1.0 });getPage(1)取出第一页页码从 1 开始getViewport({ scale: 1.0 })以 100% 缩放计算页面可见区域返回包含width、height、transform等信息的视口对象。调整scale如1.5、2.0即可控制输出图片的分辨率这是实现PDF 转高清 PNG最直接的旋钮。4.4 创建 Node CanvascanvasFactoryconst canvasFactory pdfDocument.canvasFactory; const canvasAndContext canvasFactory.create( viewport.width, viewport.height ); const renderContext { canvasContext: canvasAndContext.context, viewport, };在浏览器环境中pdf.js 渲染依赖 DOMcanvas而在 Node 环境中没有 DOM因此 pdf.js 在服务端构建中提供canvasFactory——一个负责创建/回收画布的工厂对象pdfDocument.canvasFactory由pdfjs-dist的 Node 入口在初始化时注入基于node-canvas实现因此无需手动 new CanvascanvasFactory.create(width, height)返回{ canvas, context }其中canvas是 Node Canvas 实例context是 2D 绘图上下文。这一机制贯穿整个渲染管线在 src/display/canvas.js 中栅格化器内部通过this.canvasFactory.create(...)大量分配临时画布例如透明遮罩 smask、裁剪与缩放缓冲区并在用完后由this.canvasFactory.destroy(...)回收见 canvas.js 中create/destroy/reset的众多调用点。理解这一点有助于解释为什么服务端渲染必须显式传入可用的canvasFactory也说明示例代码中直接使用pdfDocument.canvasFactory是一种简洁且正确的做法。4.5 渲染页面并输出 PNGconst renderTask page.render(renderContext); await renderTask.promise; // Convert the canvas to an image buffer. const image canvasAndContext.canvas.toBuffer(image/png); fs.writeFile(output.png, image, function (error) { if (error) { console.error(Error: error); } else { console.log(Finished converting first page of PDF file to a PNG image.); } }); // Release page resources. page.cleanup();page.render(renderContext)返回一个renderTask其promise在绘制完成时 resolve——必须await之后再取画布内容否则拿到的还是空白画布canvas.toBuffer(image/png)是 Node Canvas 提供的编码接口将画布像素编码为 PNG 的Bufferfs.writeFile将其写入output.png写入路径相对于当前工作目录examples/node/pdf2png/page.cleanup()释放页面级资源字体、图像缓存等避免长时间运行的服务内存膨胀更完整的生命周期管理还应像 getinfo.mjs 那样在结束时调用loadingTask.destroy()销毁整个文档对象try/catch包裹主流程加载或渲染失败时打印reason便于排查。五、核心 API 速查表环节API作用对应源码位置加载文档getDocument({ data, cMapUrl, cMapPacked, standardFontDataUrl })创建加载任务解析 PDFpdf2png.mjs 第 33–38 行等待解析loadingTask.promiseresolve 为PDFDocumentProxy同上第 41 行取页pdfDocument.getPage(1)获取第 1 页从 1 计数第 44 行视口page.getViewport({ scale: 1.0 })计算页面尺寸与变换控制分辨率第 47 行建画布pdfDocument.canvasFactory.create(w, h)Node 环境下创建画布与 2D 上下文第 46–51 行渲染page.render(renderContext)→renderTask.promise把页面绘制进画布第 57–58 行编码输出canvas.toBuffer(image/png)fs.writeFile生成 PNG 文件第 60–67 行资源释放page.cleanup()/loadingTask.destroy()释放页面/文档资源第 69 行 / getinfo.mjs 第 54 行六、常见问题与调优建议Cannot find module pdfjs-dist/legacy/build/pdf.mjs说明尚未执行gulp dist-install先在仓库根目录运行npm install与gulp dist-install把本地构建产物安装进node_modules。中文/日文等 PDF 乱码检查cMapUrl、cMapPacked、standardFontDataUrl三个配置是否指向有效的pdfjs-dist资源目录仓库中对应的原始资源位于 external/bcmaps 与 external/standard_fonts构建时会随dist任务复制进发行包。输出图片模糊调大getViewport({ scale })的scale值例如2.0可得到 2 倍像素密度输出相应地画布尺寸与渲染耗时、内存占用都会增大。转换多页 PDF在pdfDocument.numPages范围内循环getPage(i)并逐页渲染即可把输出文件名与页码关联如output-${i}.png。内存与资源长时间批量转换时每页渲染完调用page.cleanup()全部结束后调用loadingTask.destroy()并配合canvasFactory.destroy(canvasAndContext)归还画布对象。七、小结pdf2png示例用不到 70 行代码展示了 pdf.js 在 Node.js 环境下PDF → PNG的完整链路其核心价值在于揭示了canvasFactory 抽象——pdf.js 通过工厂模式把画布创建与栅格化解耦从而让同一套渲染内核同时运行在浏览器 DOM 与 Node 服务端给出了cmap / 标准字体等资源路径配置的最佳实践这是服务端渲染中文等复杂 PDF 的关键提供了一个可复制的模板修改scale控制分辨率、循环页码实现批量转换、接入canvasFactory.destroy与loadingTask.destroy完善资源回收即可扩展为生产级的文档转图片服务。如需进一步探索可对照阅读同仓库的 examples/node/getinfo.mjs元数据与文本抽取和 examples/text-only/pdf2svg.mjs文本转 SVG以及渲染内核实现 src/display/canvas.js从而全面掌握 pdf.js 的文档处理能力。【免费下载链接】pdf.jsPDF Reader in JavaScript项目地址: https://gitcode.com/gh_mirrors/pd/pdf.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/18 1:31:13

单片机毕设项目:基于 STM32 或 51 单片机的自动降温婴儿床智能控制系统设计 基于 STM32 或 51 单片机的居家婴幼儿安全监护硬件平台设计(025407)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于嵌入式单片机,Java、小程序技术领域和毕业项目实战 ✌️…

2026/9/18 3:46:18

Python视觉识别项目实战:从猫狗识别到模型部署

1. 项目定位:Python视觉识别到底在做什么先聊点实在的。我在社区和群里经常看到有人问"Python学完之后能干什么",或者更直接一点,"人工智能大作业选什么方向好"。我的看法一直很明确:视觉识别是Python进阶路线…

2026/9/18 3:46:18

HAProxy负载均衡实战:从配置到故障转移的完整实验指南

说实话,我第一次看到“HAProxy实验”这个标题时,就想起当年自己搭第一个负载均衡集群时手忙脚乱的样子。那时候连四层和七层都分不清,配置写错了就在那一个劲地重启服务,日志又没开,排查了半天才发现是后端健康检查路径…

2026/9/18 3:46:18

Python排序算法全攻略:从冒泡到Timsort的工程实践

排序算法这个老生常谈的话题,几乎所有学Python的人都会碰到。面试要考,日常写业务代码要处理榜单、排行榜、数据分析前的预处理也绕不开。我在带新人时最常被问到的就是:网上讲排序的教程这么多,背哪个?用哪个&#xf…

2026/9/18 3:46:18

AI芯片设计从入门到进阶:避开放弃陷阱的系统学习路径

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/18 3:41:18

异常处理与排查:从编译期异常到运行时异常的完整指南

1. 从一条报错说起:异常到底是什么你有没有发现,"异常"这个关键词能挂出一长串热搜词:java 异常、python 异常怎么写、数组越界异常、编译期异常、windows 无法加载设备驱动程序 代码 31、我们的系统检测到您的计算机网络中存在异常…

2026/9/16 12:52:37

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/18 0:01:09

Google Colab 实战:运行模型、数据加载与报错排查

1. 为什么我劝你先搞懂 Colab 的运行模型1.1 Colab 到底是什么,跟本地跑代码差在哪Google Colab 简单说就是一台跑在浏览器里的 Linux 虚拟机,你打开一个 Notebook,背后就连上了一台带 GPU 的远程机器。你在单元格里敲的每一行 Python&#x…

2026/9/18 0:01:09

C语言数据类型与表达式详解

1. C语言数据与数据类型概述在C语言编程中,数据是程序处理的核心对象。理解数据的分类和特性是掌握C语言的基础。C语言中的数据主要分为四大类:常量、变量、表达式和函数。这些数据类型构成了C语言程序的基本元素,每种类型都有其独特的特性和…

2026/9/18 0:01:09

SQL时间字段指定时间段查询:区间语义、索引与时区避坑

上周排查一个线上问题&#xff0c;用户反馈"昨天的订单一条都没查到"&#xff0c;但数据库里明明躺着两千多条。最后定位下来&#xff0c;不是数据丢了&#xff0c;也不是接口挂了&#xff0c;而是那个查询条件把时间段写成了> 2024-05-20 00:00:00 AND < 2024…

2026/9/16 22:55:57

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行&#xff0c;Type-C接口算是典型的“看着简单&#xff0c;做起来全坑”的东西。光引脚就24个&#xff0c;高低速信号、电源、控制线全部塞在一个小小的连接器里&#xff0c;如果PCB布局不做规划&#xff0c;打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/16 22:56:09

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/16 22:56:16

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码