前端实现 PDF 文件预览的 7 种方案详解

十念  金牌会员 | 2025-3-11 05:27:24 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 990|帖子 990|积分 2970

前端实现 PDF 文件预览的 7 种方案详解


一、原生浏览器方案

1. 使用 <embed> 标签

  1. <embed
  2.   src="document.pdf"
  3.   type="application/pdf"
  4.   width="100%"
  5.   height="600px"
  6. />
复制代码
优点


  • 零依赖原生支持
  • 主动表现控制栏(打印/下载按钮)
缺点


  • 差别浏览器样式差异大
  • 无法深度定制界面
  • 移动端兼容性较差
2. 使用 <object> 标签

  1. <object
  2.   data="document.pdf"
  3.   type="application/pdf"
  4.   width="100%"
  5.   height="600px"
  6. >
  7.   <p>您的浏览器不支持PDF预览,请<a href="document.pdf">下载查看</a></p>
  8. </object>
复制代码
3. 使用 <iframe> 标签

  1. <iframe
  2.   src="document.pdf#view=FitH"
  3.   width="100%"
  4.   height="600px"
  5.   frameborder="0"
  6. ></iframe>
复制代码
参数技巧


  • #view=FitH 水平适配
  • #page=3 跳转指定页
  • #zoom=80 设置缩放比例

二、PDF.js 方案(Mozilla 官方方案)

1. 基础集成

  1. // 安装
  2. npm install pdfjs-dist
  3. // 组件实现
  4. import * as pdfjsLib from 'pdfjs-dist/webpack';
  5. const container = document.getElementById('viewer');
  6. pdfjsLib.getDocument('document.pdf').promise.then(pdf => {
  7.   for(let pageNum = 1; pageNum <= pdf.numPages; pageNum++){
  8.     pdf.getPage(pageNum).then(page => {
  9.       const canvas = document.createElement('canvas');
  10.       const context = canvas.getContext('2d');
  11.       
  12.       const viewport = page.getViewport({ scale: 1.5 });
  13.       canvas.width = viewport.width;
  14.       canvas.height = viewport.height;
  15.       page.render({
  16.         canvasContext: context,
  17.         viewport: viewport
  18.       });
  19.       
  20.       container.appendChild(canvas);
  21.     });
  22.   }
  23. });
复制代码
2. 高级功能实现

  1. // 文字层渲染(支持复制)
  2. page.getTextContent().then(textContent => {
  3.   pdfjsLib.renderTextLayer({
  4.     textContent: textContent,
  5.     container: textLayerDiv,
  6.     viewport: viewport,
  7.     textDivs: []
  8.   });
  9. });
  10. // 添加标注功能
  11. const annotations = page.getAnnotations();
  12. annotations.then(annots => {
  13.   annots.forEach(annot => {
  14.     // 绘制高亮/下划线等
  15.   });
  16. });
复制代码
优势


  • 完全控制渲染流程
  • 支持文本选择/搜索
  • 可扩展标注功能
  • 支持WebGL加快渲染
缺点


  • 首次加载须要下载约 1MB 资源
  • 复杂文档渲染性能需优化

三、流行第三方库方案

1. React 生态:react-pdf-viewer

  1. import { Viewer } from '@react-pdf-viewer/core';
  2. import '@react-pdf-viewer/core/lib/styles/index.css';
  3. function App() {
  4.   return (
  5.     <div style={{ height: '750px' }}>
  6.       <Viewer fileUrl="document.pdf" />
  7.     </div>
  8.   );
  9. }
复制代码
2. Vue 生态:vue-pdf-embed

  1. <template>
  2.   <vue-pdf-embed
  3.     :source="pdfSource"
  4.     :page="currentPage"
  5.     @rendered="handleRendered"
  6.   />
  7. </template>
  8. <script>
  9. import VuePdfEmbed from 'vue-pdf-embed';
  10. export default {
  11.   components: { VuePdfEmbed },
  12.   data() {
  13.     return { currentPage: 1 }
  14.   }
  15. }
  16. </script>
复制代码

四、云服务方案

Google Docs Viewer

  1. <iframe
  2.   src="https://docs.google.com/gview?url=YOUR_PDF_URL&embedded=true"
  3.   style="width:100%; height:600px;"
  4.   frameborder="0"
  5. ></iframe>
复制代码
注意事项


  • 需处理 URL 编码
  • 国内访问须要梯子
  • 有隐私泄漏风险

五、服务端渲染方案

1. PDF 转图片方案

  1. // 服务端(Node.js)
  2. const pdf2pic = require('pdf2pic');
  3. const options = {
  4.   density: 100,   // 输出质量
  5.   format: "png",  // 输出格式
  6.   width: 800,     // 输出宽度
  7.   height: 1200    // 输出高度
  8. };
  9. const convert = new pdf2pic(options);
  10. convert("document.pdf", 1)  // 转换第一页
  11.   .then(response => {
  12.     console.log(response); // { path: '/images/document.png' }
  13.   })
复制代码
2. PDF 转 HTML 方案

  1. # 使用 pdf2htmlEX 工具
  2. pdf2htmlEX --zoom 1.3 --embed-font 0 input.pdf output.html
复制代码

六、移动端优化方案

1. 手势控制实现

  1. // 使用 hammer.js 添加手势
  2. const hammer = new Hammer(pdfContainer);
  3. hammer.on('swipeleft', () => goToNextPage());
  4. hammer.on('swiperight', () => goToPrevPage());
  5. hammer.on('pinch', (e) => adjustZoom(e.scale));
复制代码
2. 性能优化技巧



  • 分页加载:仅渲染可视区域页面
  • Canvas 缓存:缓存已渲染页面
  • Web Worker:将 PDF 剖析放入 Worker 线程
  • 渐进加载:流式加载 PDF 文件

七、方案对比与选型建议

方案适用场景优点缺点原生标签快速原型开发零配置、无依赖样式不可控、功能受限PDF.js企业级复杂需求完全可控、功能强大实现成本较高第三方封装库特定框架项目开箱即用、生态整合灵活性受限云服务临时/演示场景无需维护服务端网络依赖、隐私风险服务端渲染老旧装备兼容客户端压力小服务端资源斲丧大 选型建议

  • 内部管理体系:推荐 PDF.js + 文本搜索功能
  • 移动端 H5:第三方库 + 手势优化
  • 文档型网站:原生标签 + 服务端备选方案
  • 高安全场景:私有化部署 PDF.js

扩展知识:常见标题解决方案

1. 跨域标题处理

  1. # Nginx 配置
  2. location /pdf/ {
  3.   add_header 'Access-Control-Allow-Origin' '*';
  4.   add_header 'Access-Control-Allow-Methods' 'GET';
  5. }
复制代码
2. 大文件加载优化

  1. // 分片加载
  2. const CHUNK_SIZE = 1024 * 1024; // 1MB
  3. let offset = 0;
  4. const loadChunk = () => {
  5.   fetch(url, {
  6.     headers: { 'Range': `bytes=${offset}-${offset + CHUNK_SIZE}` }
  7.   }).then(res => {
  8.     // 处理分片数据
  9.     offset += CHUNK_SIZE;
  10.     if(offset < totalSize) loadChunk();
  11.   });
  12. }
复制代码
3. 水印添加方案

  1. // Canvas 绘制水印
  2. function addWatermark(canvas, text) {
  3.   const ctx = canvas.getContext('2d');
  4.   ctx.fillStyle = 'rgba(0,0,0,0.1)';
  5.   ctx.font = '20px Arial';
  6.   ctx.rotate(-30 * Math.PI / 180);
  7.   ctx.fillText(text, 50, 100);
  8. }
复制代码

总结

前端 PDF 预览须要根据实际场景选择技能方案,对于须要深度定制和复杂交互的场景,推荐使用 PDF.js 配合 Canvas 渲染;对于追求快速实现的场景,可选用封装好的第三方库。无论选择哪种方案,都须要重点关注:

  • 性能优化:大文件处理/移动端适配
  • 安全控制:防止未授权访问/添加水印
  • 用户体验:加载进度指示/错误处理
  • 可访问性:支持屏幕阅读器/键盘操作

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

十念

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表