node.js读取pdf需用buffer而非文本编码,pdf-parse无法解析表格结构,应选pdfjs-dist等支持布局分析的库,中文乱码源于字体映射缺失,最优解是推动上游改用excel/csv。

Node.js 读取本地 PDF 文件失败:路径和编码问题最常见
VSCode 本身不提供 PDF 解析能力,必须依赖 Node.js 第三方库。但很多用户一上来就 fs.readFileSync('./data.pdf') 报错,根本原因是 PDF 是二进制格式,不能当文本直接读取——fs.readFileSync 默认以 UTF-8 解码,遇到非文本字节直接抛 ERR_INVALID_UTF8_BYTE。
正确做法是显式指定 encoding: null(返回 Buffer)或用 fs.readFile 异步读取:
const pdfBuffer = fs.readFileSync('./invoice.pdf', { encoding: null });
注意:encoding: null 不可写作 encoding: 'buffer'(后者在旧版 Node 中不被识别);路径必须是绝对路径或确保工作目录正确(VSCode 终端默认工作目录是打开的文件夹根目录,不是当前文件所在目录)。
pdf-parse 无法提取表格:PDF 本质是图形流,不是结构化数据
pdf-parse 是轻量级选择,但它只做 OCR 前的文本提取——把 PDF 页面里“看起来像文字”的东西按渲染顺序拼成字符串。它不识别表格线、单元格边界,更不会还原行列关系。你拿到的是一长串换行混乱的文本,split('\n') 后字段对不齐是常态。
真正要解析表格,得用支持布局分析的库:
-
pdfjs-dist+ 自研逻辑:需手动计算文本块坐标,判断是否在同一行/列,适合简单规整表格 -
pdf-lib不行——它只读写 PDF 结构,不解析内容 -
tabula-java绑定(如tabula-js):调用 Java 后端,能识别表格线,但需要本地装 Java,跨平台部署麻烦 -
pdf2table(Node 封装版):底层用 Python 的camelot或tabula-py,稳定性依赖 Python 环境
如果只是偶尔处理几份固定格式的 PDF,优先试 pdfjs-dist 配合坐标过滤;若需稳定产出 CSV,建议直接导出为 Excel 再用 xlsx 库读——比硬啃 PDF 可靠得多。
在 VSCode 终端运行时提示 “Cannot find module ‘pdfjs-dist’”
这不是 VSCode 的问题,而是 Node 模块未安装或安装位置不对。VSCode 内置终端本质就是系统 shell,它运行的是你当前终端环境里的 Node 和 npm。
检查三件事:
- 确认你在项目根目录下执行了
npm install pdfjs-dist(不是全局安装) - 确认
node_modules目录真实存在且包含pdfjs-dist子目录 - 确认你的 JS 文件里用了正确的引入方式:
import { getDocument } from 'pdfjs-dist/build/pdf.mjs';(ESM)或const { getDocument } = require('pdfjs-dist/build/pdf.node.cjs');(CommonJS)——不同构建版本路径不同,官方案例常省略.mjs后缀导致报错
另外,pdfjs-dist 默认使用 Promise API,别忘了 await 或 .then(),否则 numPages 会是 Promise 对象而非数字。
中文 PDF 解析乱码或漏字:字体映射没加载全
pdfjs-dist 解析中文 PDF 时,如果 PDF 内嵌字体不完整或用了非标准 CID 字体,会出现方框、空格或部分文字消失。这不是编码问题,而是字体描述缺失。
解决方法只有两个:
- 强制启用字体降级:在
getDocument参数中加disableFontFace: false(默认已是 false,但某些打包环境会覆盖) - 手动注入字体映射:通过
pdfjsLib.GlobalWorkerOptions.workerSrc指向预编译的 worker 文件,并确保该 worker 支持 CMap(中文字符映射表)——这通常意味着你得用官方发布的完整版pdfjs-dist,而不是精简版
临时验证是否字体问题:把 PDF 用 Adobe Acrobat “另存为” → “优化的 PDF”,再试一次。如果好了,说明原 PDF 字体嵌入不规范,自动化流程里就得加一步预处理。
表格解析这事,从 PDF 开始就注定是妥协的艺术——格式越自由,结果越不可控。与其花三天调参,不如推动上游改用 Excel 或 CSV 输出。











