前端实现 PDF 文件预览的 7 种方案详解
一、原生浏览器方案
1. 使用 <embed> 标签
- <embed
- src="document.pdf"
- type="application/pdf"
- width="100%"
- height="600px"
- />
复制代码 优点:
缺点:
- 差别浏览器样式差异大
- 无法深度定制界面
- 移动端兼容性较差
2. 使用 <object> 标签
- <object
- data="document.pdf"
- type="application/pdf"
- width="100%"
- height="600px"
- >
- <p>您的浏览器不支持PDF预览,请<a href="document.pdf">下载查看</a></p>
- </object>
复制代码 3. 使用 <iframe> 标签
- <iframe
- src="document.pdf#view=FitH"
- width="100%"
- height="600px"
- frameborder="0"
- ></iframe>
复制代码 参数技巧:
- #view=FitH 水平适配
- #page=3 跳转指定页
- #zoom=80 设置缩放比例
二、PDF.js 方案(Mozilla 官方方案)
1. 基础集成
- // 安装
- npm install pdfjs-dist
- // 组件实现
- import * as pdfjsLib from 'pdfjs-dist/webpack';
- const container = document.getElementById('viewer');
- pdfjsLib.getDocument('document.pdf').promise.then(pdf => {
- for(let pageNum = 1; pageNum <= pdf.numPages; pageNum++){
- pdf.getPage(pageNum).then(page => {
- const canvas = document.createElement('canvas');
- const context = canvas.getContext('2d');
-
- const viewport = page.getViewport({ scale: 1.5 });
- canvas.width = viewport.width;
- canvas.height = viewport.height;
- page.render({
- canvasContext: context,
- viewport: viewport
- });
-
- container.appendChild(canvas);
- });
- }
- });
复制代码 2. 高级功能实现
- // 文字层渲染(支持复制)
- page.getTextContent().then(textContent => {
- pdfjsLib.renderTextLayer({
- textContent: textContent,
- container: textLayerDiv,
- viewport: viewport,
- textDivs: []
- });
- });
- // 添加标注功能
- const annotations = page.getAnnotations();
- annotations.then(annots => {
- annots.forEach(annot => {
- // 绘制高亮/下划线等
- });
- });
复制代码 优势:
- 完全控制渲染流程
- 支持文本选择/搜索
- 可扩展标注功能
- 支持WebGL加快渲染
缺点:
- 首次加载须要下载约 1MB 资源
- 复杂文档渲染性能需优化
三、流行第三方库方案
1. React 生态:react-pdf-viewer
- import { Viewer } from '@react-pdf-viewer/core';
- import '@react-pdf-viewer/core/lib/styles/index.css';
- function App() {
- return (
- <div style={{ height: '750px' }}>
- <Viewer fileUrl="document.pdf" />
- </div>
- );
- }
复制代码 2. Vue 生态:vue-pdf-embed
- <template>
- <vue-pdf-embed
- :source="pdfSource"
- :page="currentPage"
- @rendered="handleRendered"
- />
- </template>
- <script>
- import VuePdfEmbed from 'vue-pdf-embed';
- export default {
- components: { VuePdfEmbed },
- data() {
- return { currentPage: 1 }
- }
- }
- </script>
复制代码 四、云服务方案
Google Docs Viewer
- <iframe
- src="https://docs.google.com/gview?url=YOUR_PDF_URL&embedded=true"
- style="width:100%; height:600px;"
- frameborder="0"
- ></iframe>
复制代码 注意事项:
- 需处理 URL 编码
- 国内访问须要梯子
- 有隐私泄漏风险
五、服务端渲染方案
1. PDF 转图片方案
- // 服务端(Node.js)
- const pdf2pic = require('pdf2pic');
- const options = {
- density: 100, // 输出质量
- format: "png", // 输出格式
- width: 800, // 输出宽度
- height: 1200 // 输出高度
- };
- const convert = new pdf2pic(options);
- convert("document.pdf", 1) // 转换第一页
- .then(response => {
- console.log(response); // { path: '/images/document.png' }
- })
复制代码 2. PDF 转 HTML 方案
- # 使用 pdf2htmlEX 工具
- pdf2htmlEX --zoom 1.3 --embed-font 0 input.pdf output.html
复制代码 六、移动端优化方案
1. 手势控制实现
- // 使用 hammer.js 添加手势
- const hammer = new Hammer(pdfContainer);
- hammer.on('swipeleft', () => goToNextPage());
- hammer.on('swiperight', () => goToPrevPage());
- hammer.on('pinch', (e) => adjustZoom(e.scale));
复制代码 2. 性能优化技巧
- 分页加载:仅渲染可视区域页面
- Canvas 缓存:缓存已渲染页面
- Web Worker:将 PDF 剖析放入 Worker 线程
- 渐进加载:流式加载 PDF 文件
七、方案对比与选型建议
方案适用场景优点缺点原生标签快速原型开发零配置、无依赖样式不可控、功能受限PDF.js企业级复杂需求完全可控、功能强大实现成本较高第三方封装库特定框架项目开箱即用、生态整合灵活性受限云服务临时/演示场景无需维护服务端网络依赖、隐私风险服务端渲染老旧装备兼容客户端压力小服务端资源斲丧大 选型建议:
- 内部管理体系:推荐 PDF.js + 文本搜索功能
- 移动端 H5:第三方库 + 手势优化
- 文档型网站:原生标签 + 服务端备选方案
- 高安全场景:私有化部署 PDF.js
扩展知识:常见标题解决方案
1. 跨域标题处理
- # Nginx 配置
- location /pdf/ {
- add_header 'Access-Control-Allow-Origin' '*';
- add_header 'Access-Control-Allow-Methods' 'GET';
- }
复制代码 2. 大文件加载优化
- // 分片加载
- const CHUNK_SIZE = 1024 * 1024; // 1MB
- let offset = 0;
- const loadChunk = () => {
- fetch(url, {
- headers: { 'Range': `bytes=${offset}-${offset + CHUNK_SIZE}` }
- }).then(res => {
- // 处理分片数据
- offset += CHUNK_SIZE;
- if(offset < totalSize) loadChunk();
- });
- }
复制代码 3. 水印添加方案
- // Canvas 绘制水印
- function addWatermark(canvas, text) {
- const ctx = canvas.getContext('2d');
- ctx.fillStyle = 'rgba(0,0,0,0.1)';
- ctx.font = '20px Arial';
- ctx.rotate(-30 * Math.PI / 180);
- ctx.fillText(text, 50, 100);
- }
复制代码 总结
前端 PDF 预览须要根据实际场景选择技能方案,对于须要深度定制和复杂交互的场景,推荐使用 PDF.js 配合 Canvas 渲染;对于追求快速实现的场景,可选用封装好的第三方库。无论选择哪种方案,都须要重点关注:
- 性能优化:大文件处理/移动端适配
- 安全控制:防止未授权访问/添加水印
- 用户体验:加载进度指示/错误处理
- 可访问性:支持屏幕阅读器/键盘操作
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |