介绍
PDF.js 是 Mozilla(火狐官方)2011年开源、全JS编写的PDF前端渲染引擎,无任何浏览器插件、无客户端软件依赖,依靠HTML5 Canvas/Web Worker/DOM在浏览器原生解析渲染PDF,火狐浏览器内置PDF阅读器底层就是PDF.js。
- 开源协议:Apache2.0(免费商用、无版权限制)
- 仓库:https://github.com/mozilla/pdf.js
- 分发包:pdfjs-dist(生产使用打包产物)
- 适用:Web网页预览PDF、后端文件预览系统、KKFileView前端内核、Vue/React内嵌PDF预览
对比传统PDF预览方案优势
| 方案 | 缺点 | PDF.js优势 |
|---|---|---|
| iframe直接打开PDF | 依赖浏览器内核、UI不可定制、部分浏览器不兼容 | 完全自定义UI、跨浏览器统一表现 |
| 后端转图片预览 | 服务器算力消耗大、不能选文字/搜索 | 前端渲染、支持文本复制、全文检索 |
| Adobe插件/NPAPI | 现代浏览器已废弃、安全漏洞 | 纯前端、安全无插件 |
适用场景
- OA/档案系统网页在线PDF预览
- 文档管理系统前端预览(你做的文件智能体RAG预览)
- 浏览器在线打开本地PDF文件
- KKFileView、OnlyOffice预览备选前端渲染内核
- 移动端H5在线预览PDF
版本选择
4.x/5.x/6.x(开发部署复杂,不推荐):内核改用mjs模块;本地Vite+FastAPI跨端口预览需配置MIME、改源码,适合Nginx同域部署项目。
3.11.174 legacy(推荐):全文件js、白名单原生数组,只需添加前后端域名即可跨接口加载PDF,零额外配置,适配前后端分离本地调试。
项目选型:跨端口预览选3.11,正式同域上线可选4.x及以上。
三层架构
PDF.js整体分Core内核层、Display渲染API层、Viewer完整UI层三层,项目开发按需选用:
1.Core 内核层(底层解析引擎)
- 职责:二进制PDF文件解析、PDF字典/流/字体/图像解码、PDF语法校验,不对外暴露稳定API,运行在Web Worker中
- pdf.worker.js 就是Core打包产物,所有PDF解析任务在Worker子线程执行,不阻塞页面主线程渲染
2.Display 显示层(业务开发常用API层)
对外提供稳定API,开发者手动绘制Canvas自定义预览(自己做翻页、缩放UI),无自带工具栏,日常手写预览用这一层。
核心入口:getDocument() 加载PDF文档、pdfDoc.getPage() 获取单页、page.render() 绘制到Canvas。
3.Viewer 完整UI层(开箱即用阅读器)
基于Display封装一套完整PDF阅读器(web/viewer.html),自带:页码跳转、缩放、旋转、全文搜索、缩略图侧边栏、打印、下载、书签、批注面板,直接iframe引入即可快速实现完整预览,企业预览系统首选。
目录结构
pdfjs-dist/
├─ build/
│ ├─ pdf.js / pdf.min.js # Display核心主库
│ └─ pdf.worker.js / min.js # Core解析Worker脚本(必须单独部署)
└─ web/ # Viewer完整阅读器UI资源
├─ viewer.html # 阅读器入口页面
├─ viewer.js / viewer.css
└─ locale/ # 多语言包(含zh-CN中文)
两种接入方式
方式1:iframe引入Viewer(最简)
直接通过地址传PDF文件路径,自带全套工具栏,支持中文。
<!-- 1.本地部署web文件夹后使用 -->
<iframe src="./web/viewer.html?file=/static/test.pdf#locale=zh-CN" width="100%" height="800px"></iframe>
<!-- #locale=zh-CN 强制中文界面 -->
- 参数:
file=文件URL(文件需跨域允许,同域/后端代理接口) - 高级:可通过
#page=3直接打开第3页、隐藏下载/打印按钮(修改viewer配置)
方式2:原生API手动渲染(自定义预览,无自带工具栏,Vue/React内嵌)
NPM引入(Vite/Webpack项目)
npm install pdfjs-dist
import * as pdfjsLib from 'pdfjs-dist/build/pdf'
import pdfWorker from 'pdfjs-dist/build/pdf.worker?url'
// 配置Worker
pdfjsLib.GlobalWorkerOptions.workerSrc = pdfWorker;
// 后续getDocument同上面代码
特性
- Web Worker异步解析:PDF解析全在子线程,超大PDF不会卡死页面,支持多PDF独立Worker隔离
- 中文PDF兼容:复杂内嵌字体需要引入
cmap字体映射包(pdfjs-dist/cmaps目录),缺字会乱码 - 两种渲染模式:
- Canvas模式:默认,像素渲染、兼容性最好
- SVG模式:矢量渲染,文字可原生选中,性能略差
- 懒加载/分片加载:大PDF分段请求字节流,不用一次性下载全文件即可渲染首页
- 文本提取:精准提取每页文字,实现网页全文检索、复制PDF文字(后端转图片方案做不到)
- 批注解析:读取PDF内置注释、高亮、印章批注
常见问题&优化
1.中文乱码/缺字
引入cmap资源,配置cMapUrl:
getDocument({url:'xx.pdf',cMapUrl:'/cmaps/',cMapPacked:true})
2.跨域报错(后端PDF文件访问)
后端接口配置CORS跨域头,或前端通过同域代理接口转发PDF流。
3.超大PDF优化(几百MB)
开启分片rangeChunkSize、分页懒加载(只渲染可视区域页面)、禁用预加载全部页码。
4.Vite打包Worker报错
Worker路径用?url引入:import workerUrl from 'pdfjs-dist/build/pdf.worker?url'
局限性
- 不支持PDF编辑:仅解析渲染、提取文本,无法修改PDF内容(如需编辑用PDFKit、pdf-lib生成/修改)
- 加密PDF(用户密码加密)需要手动传入密码参数才能打开
- 超大PDF(1GB+)前端全量加载性能一般,建议后端分页预渲染缩略图+前端分页加载