一、前言
在前端开发中,渲染PDF文件一直是一项重要而挑战性的任务。而今,我们可以借助pdf.js库来轻松实现这一目标。pdf.js是一个开源的JavaScript库,它可以在浏览器中渲染PDF文件,实现了在网页上查看PDF文档的功能。它提供了丰富的API和功能,使得在前端页面展示PDF文件变得轻而易举。让我们一起探索pdf.js的奇妙之处,轻松实现前端PDF文件的渲染与展示吧!
二、简介
1、pdf.js介绍
pdf.js是一款基于JavaScript的开源PDF阅读器组件,可以在网页中直接显示和操作PDF文件,目前已知的前端渲染pdf组件都是基于pdf.js进行封装。
git地址:https://github.com/mozilla/pdf.js
注:开源且免费
2、插件版本参数
| 插件 | 版本 |
| Node | v22.13.0 |
@types/react | ^18.0.33 |
@types/react-dom | ^18.0.11 |
| pdfjs-2.5.207-es5-dist.zip (viewer.js使用方式) | 2.5.207 |
| pdfjs-dist (canvas渲染方式) | 3.6.172 |
三、通过viewer.html实现预览(推荐)
1、介绍
除了PDF预览,还待配套的工具栏,支持功搜索、缩放、目录、打印等功能~
Demo如图:

2、部署
【1】下载插件包
下载地址:https://github.com/mozilla/pdf.js/releases/tag/v2.5.207

【2】客户端方式
把下载后的pdfjs-2.5.207-es5-dist.zip解压后,放在项目中的public文件夹下

【3】服务端方式
pdf.js包仍然放在public目录下(或者服务端目录下)
const pdfServerUrl = '/pdfjs-2.5.207-es5-dist/web/viewer.html'
一个可以获取pdf文件二进制流的地址(需要同源)
....
const pdfInfoUrl = `${location.origin}/xxx/xx.pdf`;
const url = `${pdfServerUrl}?file=${encodeURIComponent(pdfInfoUrl)}`
...
<iframe id='pdfIframe' src={url} width="100%" height="100%"></iframe>3、使用方法
【1】预览PDF文件
1)客户端方式(基于React框架为例)
const viewPDF: React.FC = () => {
// pdf文件路径,放在项目的public目录下
const pdfUrl = '/A.pdf';
//pdf.js库的代码,放在项目的public目录下
const pdfServerUrl = '/pdfjs-2.5.207-es5-dist/web/viewer.html'
const url = `${pdfServerUrl}?file=${pdfUrl}`
return <>
<h1>pdf 搜索(基于pdf-dist,pdf_viewer.html)</h1>
<iframe id='pdfIframe' src={url} width="100%" height="100%"></iframe>
</>;
}2)服务端方式
通过axios接口获取文件的arraybuffer,再把arraybuffer转换成二进制Blob,最后把Bolb转成blob:url传给viewer.html
...
import axios from 'axios';
...
const [pdfUrl, setPdfUrl] = useState<string>('');
const getPDFViewUrl = (fileName: any) => {
axios({
method: 'get',
url: `URL`,//文件下载的url
responseType: 'arraybuffer'
}).then(response =>{
const blob = new Blob([response.data], { type: 'application/pdf' });
const blobUrl = URL.createObjectURL(blob);
console.log('zyk===>', blobUrl)
setPdfUrl(`${pdfServerUrl}?file=${blobUrl}`)
})
};
return (
<>
<iframe id="pdfIframe" src={pdfUrl} width="100%" height="100%"></iframe>
</>
);【2】外部搜索条件触发pdf.js的搜索逻辑
- 跳转至第一个匹配的内容
- 匹配内容高亮
const viewPDF: React.FC = () => {
// pdf文件路径,放在项目的public目录下
const pdfUrl = '/A.pdf';
//pdf.js库的代码,放在项目的public目录下
const pdfServerUrl = '/pdfjs-2.5.207-es5-dist/web/viewer.html'
const url = `${pdfServerUrl}?file=${pdfUrl}`
let pdfContentWindow: any = null; //缓存iframContent
const getPdfContent = () => {
const pdfFrame: any = document.getElementById('pdfIframe');
if (!pdfFrame) {
return;
}
pdfContentWindow = pdfFrame.contentWindow;
//pdf组件部分信息,包括:当前页码、总共页码等
console.log('page===>', pdfContentWindow.PDFViewerApplication);
}
const onSearchForOut = (searchText: string) => {
pdfContentWindow.postMessage(searchText, '*');
pdfContentWindow.addEventListener('message', (e: any) => {
// 高亮匹配结果
pdfContentWindow.PDFViewerApplication.findBar.findField.value = e.data;
pdfContentWindow.PDFViewerApplication.findBar.highlightAll.checked = true; pdfContentWindow.PDFViewerApplication.findBar.dispatchEvent('highlightallchange');
//触发搜索项‘下一个'事件
pdfContentWindow.PDFViewerApplication.findBar.dispatchEvent('again', false);
}, false);
}
useEffect(() => {
getPdfContent();
setTimeout(() => {
// 外部的搜索条件
onSearchForOut('阳区CBD核心区')
}, 3* 1000)
}, []);
return <>
<h1>pdf 搜索(基于pdf-dist,pdf_viewer.html)</h1>
<iframe id='pdfIframe' src={url} width="100%" height="100%"></iframe>
</>;
}四、把pdf渲染为canvas实现预览
1、安装
npm install pdfjs-dist --save
2、功能实现
【1】实现pdf预览
import { Button } from 'antd';
import { useState, useEffect, useRef } from 'react';
import * as pdfjsLib from 'pdfjs-dist'; // 引入pdfjs-dist
const pdfUrl = '/zyk.pdf'; // pdf 文件路径,pdf文件存放于public目录下
const workerUrl = `/pdf.worker.min.js`; //webworker存放于public目录下
pdfjsLib.GlobalWorkerOptions.workerSrc = workerUrl;
const viewPdf = (props: {height: string}) => {
const {height} = props;
const pdfContainerRef = useRef<any>(null);
const [pagesList, setPagesList] = useState<any>([]);
const scale = 2; // 缩放比例
// 渲染单个页面
const renderPage = async (page: any, pageNumber: number) => {
const viewport = page.getViewport({ scale });
const pageContentDom = document.createElement('div');
pageContentDom.id = `pdfPage-content-${pageNumber}`;
pageContentDom.style.width = `${viewport.width}px`;
pageContentDom.style.height = `${viewport.height}px`;
pageContentDom.style.position = 'relative';
// 创建 Canvas 元素
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
canvas.id=`pdfPage-${pageNumber}`
canvas.width = viewport.width;
canvas.height = viewport.height;
canvas.style.border = '1px solid black';
pageContentDom.appendChild(canvas);
pdfContainerRef.current.appendChild(pageContentDom);
// 渲染 PDF 页面到 Canvas
await page.render({
canvasContext: context,
viewport,
}).promise;
};
// 渲染 PDF 页面
const renderPagesGroup = ( pages: any) => {
pages.forEach(({page}:any, index: number) => {
renderPage(page, index);
});
};
// 加载 PDF 文件
const loadPdf = async (url: any) => {
const pdf = await pdfjsLib.getDocument(url).promise;
const pages: any[] = [];
for (let i = 1; i <= pdf.numPages; i++) {
const page = await pdf.getPage(i);
const textContent = await page.getTextContent();
pages.push({
page,
textContent
});
}
setPagesList(pages);
renderPagesGroup(pages);
};
useEffect(() => {
loadPdf(pdfUrl);
}, []);
return <>
<div>
<h1>PDF 搜索(基于@pdfjs-dist-自定义实现)</h1>
<div>
<div style={{ height: height || '500px' }}>
{/* PDF 容器 *




