当前位置: 首页 > news >正文

Vue中最简单的PDF引入方法及优缺点分析

在Vue项目中引入PDF文件有多种方法,下面我将介绍最简单实用的几种方案

前面的3种最简单了的,直接一行代码就可以了,并且不依靠依赖,占用为0kb

1=》使用<embed>标签(最简单方法)

只需一行HTML标签,不需要安装任何额外库

所有现代浏览器都支持,浏览器直接处理PDF渲染

但是呢,有利有弊,万事两难全:

PDF查看器样式直接是固定的,在小屏幕上可能显示不佳,

无法隐藏下载/打印按钮,只能加载同源或CORS允许的PDF(跨域限制)

部分截图:

代码:

<template><div class="pdf-container"><h2>使用 &lt;embed&gt; 标签显示PDF</h2><embed src="/docs/sample.pdf" type="application/pdf" width="100%" height="600px"/></div>
</template><style scoped>
.pdf-container {max-width: 900px;margin: 0 auto;padding: 20px;background: white;border-radius: 10px;box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}h2 {color: #2c3e50;margin-bottom: 20px;text-align: center;
}
</style>

2=》使用<object>标签

显示的效果基本上和上面一样的哈

和第一种相比较的话:

优点:

  1. 兼容性更好:支持更老的浏览器

  2. 提供后备内容:当无法显示时显示自定义内容

  3. 相对更标准:符合W3C规范

缺点:

  1. 与embed类似:存在相同的样式和功能限制

  2. 实现稍复杂:需要处理后备内容

部分截图:

代码: 

<template><div class="pdf-container"><h2>使用 &lt;object&gt; 标签显示PDF</h2><object :data="pdfUrl" type="application/pdf" width="100%" height="600px"><p>无法显示PDF文件。请<a :href="pdfUrl">点击这里下载</a>。</p></object></div>
</template><script>
export default {data() {return {pdfUrl: "/docs/sample.pdf"}}
}
</script><style scoped>
/* 同上 */
</style>

3=》使用<iframe>标签

只需将PDF文件的URL作为<iframe>src属性即可。

显示的效果基本上和上面两种一样的哈

限制:

  • 如果设置有密码保护,则需要手动输入密码
  • 预览效果可能不如某些插件。

    部分截图:

     代码:

    <template>
    <div class="app-container"><div>操作指南</div>// 链接:<!-- <iframe style="width: 100%; height: 100%;" src="http://xxx.pdf"></iframe> -->//本地:
    <iframe style="width: 100%; height: 100%;" src="/docs/sample.pdf"></iframe>
    </div>
    </template>
    <script setup>
    </script>

    使用 <iframe> 标签加载本地文件,需要特别注意浏览器安全策略路径处理问题。

     

     

    4=》第三方包:

    4.1 使用PDF.js

    介绍:

    pdfjs-dist 是 Mozilla 开发的 PDF.js 库的 NPM 发行版本,用于在浏览器或 Node.js 环境中渲染和处理 PDF 文件。它提供了强大的 API,使开发者能够在网页上实现 PDF 预览文本提取表单填写等功能,无需依赖浏览器内置的 PDF 插件。

    特性

    1. 纯前端渲染:无需服务器支持,直接在浏览器中解析和渲染 PDF 文件。
    2. 跨平台兼容:支持现代浏览器(Chrome、Firefox、Safari、Edge 等)和 Node.js 环境。
    3. 高性能:使用 Web Workers 实现后台处理,避免阻塞主线程。
    4. 功能丰富
      • 文本提取与搜索
      • 页面渲染与缩放
      • 表单字段支持
      • 注释与标记
      • 书签与大纲解析
    5. 模块化设计:支持按需引入所需功能,减小打包体积。

    安装:

    #该命令会把 PDF.js 的最新稳定版本安装到项目里:
    npm install pdfjs-dist或者# 特定版本 :以 3.4.120 版本为例
    npm install pdfjs-dist@3.4.120 或者#若仅在开发阶段需要使用 PDF.js,可将其作为开发依赖进行安装:
    npm install pdfjs-dist --save-dev

    基本用法

    1,在浏览器中渲染 PDF
    import * as pdfjsLib from 'pdfjs-dist';// 配置 worker 路径(重要!)
    pdfjsLib.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjsLib.version}/pdf.worker.min.js`;// 加载并渲染 PDF
    const loadingTask = pdfjsLib.getDocument('path/to/your/pdf.pdf');
    loadingTask.promise.then(pdf => {pdf.getPage(1).then(page => {const viewport = page.getViewport({ scale: 1.5 });const canvas = document.getElementById('pdf-canvas');const context = canvas.getContext('2d');canvas.height = viewport.height;canvas.width = viewport.width;const renderContext = {canvasContext: context,viewport: viewport};page.render(renderContext);});
    });
    2,提取 PDF 文本内容
    page.getTextContent().then(textContent => {const textItems = textContent.items;const text = textItems.map(item => item.str).join(' ');console.log('提取的文本:', text);
    });
    3,在 Node.js 中使用
    const pdfjsLib = require('pdfjs-dist/legacy/build/pdf.js');
    const fs = require('fs');
    const path = require('path');// 读取 PDF 文件(Buffer 格式)
    const data = new Uint8Array(fs.readFileSync(path.join(__dirname, 'example.pdf')));// 解析 PDF
    pdfjsLib.getDocument(data).promise.then(pdf => {// 处理 PDF...
    });

    一些需要知道的:

    API:

    • getDocument:加载 PDF 文件(支持 URL、ArrayBuffer、Base64 等格式)。
    • pdf.getPage:获取指定页码的页面。
    • page.render:渲染页面到 Canvas。
    • page.getTextContent:提取页面文本内容。
    • pdf.getOutline:获取 PDF 大纲(书签)。
    • pdf.getMetadata:获取 PDF 元数据(标题、作者等)。

    注意事项

    1. Worker 配置

      • 必须通过 GlobalWorkerOptions.workerSrc 指定 worker 文件路径,否则渲染会变慢或报错。
      • 可使用 CDN 路径(如示例)或自行打包 worker 文件。
    2. CORS 问题

      • 若从远程 URL 加载 PDF,需确保服务器设置了正确的 CORS 头
    3. TypeScript 支持

      • 包内已包含类型定义,无需额外安装。
    4. 安全限制

      • 浏览器环境中无法访问本地文件系统,需通过 <input type="file"> 或拖放功能获取文件。

    代码示例:

    <template><div class="pdf-viewer"><div class="header"><h1>PDF查看器</h1><div class="controls"><button @click="zoomOut" :disabled="scale <= 0.5">-</button><span>{{ Math.round(scale * 100) }}%</span><button @click="zoomIn" :disabled="scale >= 2.0">+</button><button @click="prevPage" :disabled="pageNum <= 1">上一页</button><input v-model.number="pageNum" type="number" min="1" :max="totalPages" @change="goToPage"><span>/ {{ totalPages }}</span><button @click="nextPage" :disabled="pageNum >= totalPages">下一页</button><button @click="downloadPDF">下载PDF</button></div></div><div class="pdf-container" ref="pdfContainer"><canvas ref="pdfCanvas"></canvas><div v-if="loading" class="loader">加载中...</div></div></div>
    </template><script>
    import * as pdfjsLib from 'pdfjs-dist/build/pdf';
    import 'pdfjs-dist/build/pdf.worker.entry';export default {data() {return {pdfUrl: "/docs/sample.pdf",pdfDoc: null,pageNum: 1,totalPages: 0,scale: 1.0,loading: true}},mounted() {this.loadPdf();},methods: {async loadPdf() {this.loading = true;try {pdfjsLib.GlobalWorkerOptions.workerSrc = window.pdfjsWorker;const loadingTask = pdfjsLib.getDocument(this.pdfUrl);this.pdfDoc = await loadingTask.promise;this.totalPages = this.pdfDoc.numPages;await this.renderPage();} catch (err) {console.error('PDF加载错误:', err);alert('无法加载PDF文件');} finally {this.loading = false;}},async renderPage() {if (!this.pdfDoc) return;const page = await this.pdfDoc.getPage(this.pageNum);const canvas = this.$refs.pdfCanvas;const ctx = canvas.getContext('2d');const container = this.$refs.pdfContainer;const viewport = page.getViewport({ scale: this.scale });canvas.height = viewport.height;canvas.width = viewport.width;// 居中显示canvas.style.margin = '0 auto';canvas.style.display = 'block';const renderContext = {canvasContext: ctx,viewport: viewport};await page.render(renderContext).promise;},prevPage() {if (this.pageNum > 1) {this.pageNum--;this.renderPage();}},nextPage() {if (this.pageNum < this.totalPages) {this.pageNum++;this.renderPage();}},goToPage() {if (this.pageNum < 1) this.pageNum = 1;if (this.pageNum > this.totalPages) this.pageNum = this.totalPages;this.renderPage();},zoomIn() {if (this.scale < 2.0) {this.scale += 0.1;this.renderPage();}},zoomOut() {if (this.scale > 0.5) {this.scale -= 0.1;this.renderPage();}},downloadPDF() {const link = document.createElement('a');link.href = this.pdfUrl;link.download = 'document.pdf';document.body.appendChild(link);link.click();document.body.removeChild(link);}}
    }
    </script><style scoped>
    .pdf-viewer {font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;max-width: 1000px;margin: 20px auto;padding: 20px;background: #f8f9fa;border-radius: 12px;box-shadow: 0 6px 18px rgba(0,0,0,0.1);
    }.header {background: #2c3e50;color: white;padding: 15px 20px;border-radius: 8px 8px 0 0;margin-bottom: 20px;
    }h1 {margin: 0 0 15px 0;text-align: center;font-weight: 500;
    }.controls {display: flex;justify-content: center;align-items: center;flex-wrap: wrap;gap: 12px;
    }button {padding: 8px 16px;background: #3498db;color: white;border: none;border-radius: 4px;cursor: pointer;transition: background 0.3s;font-size: 14px;
    }button:hover {background: #2980b9;
    }button:disabled {background: #95a5a6;cursor: not-allowed;
    }input {width: 50px;padding: 8px;border: 1px solid #ddd;border-radius: 4px;text-align: center;
    }.pdf-container {position: relative;min-height: 600px;background: white;border-radius: 8px;overflow: auto;box-shadow: 0 2px 10px rgba(0,0,0,0.05);border: 1px solid #eee;
    }.loader {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);font-size: 18px;color: #7f8c8d;
    }canvas {display: block;margin: 0 auto;box-shadow: 0 2px 5px rgba(0,0,0,0.05);
    }
    </style>

    http://www.lryc.cn/news/596207.html

    相关文章:

  • Gradio, Streamlit, Dash:AI应用开发的效率之选
  • 配置https ssl证书生成
  • 拓展三字棋
  • ansible 批量 scp 和 load 镜像
  • 2025 年 7 月 21 日 AI 日报
  • 位运算符的妙用
  • 消息推送功能设计指南:精准触达与用户体验的平衡之道
  • OpenCV 零基础到项目实战 | DAY 1:图像基础与核心操作
  • Qt文件操作:读写文件的各种方法
  • 模运算常见定律
  • Java学习----Redis集群
  • Custom SRP - Draw Calls
  • Linux异常与信号处理
  • 11.【C语言学习笔记】指针(三)(回调函数、qsort排序函数、sizeof关键字和strlen函数)
  • Mixed Content错误:“mixed block“ 问题
  • 西门子 S7-1500分布式 I/O通信 :PROFINET IO 与 PROFIBUS DP核心技术详解(上)
  • 知识库搭建之Meilisearch‘s 搜索引擎-创建搜索引擎项目 测评-东方仙盟测评师
  • 【Godot4】状态栏组件StatusBar
  • python中 tqdm ,itertuples 是什么
  • RabbitMQ--批量处理
  • halcon手眼标定z方向实操矫正
  • VUE 中父级组件使用JSON.stringify 序列化子组件传递循环引用错误
  • 机器人氩弧焊保护气降成本的方法
  • Apache Ignite 的 SQL 功能和分布式查询机制
  • 50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | ImageCarousel(图片轮播组件)
  • 深度学习篇---车道线循迹
  • FPGA自学——存储器模型
  • Kafka单条消息长度限制详解及Java实战指南
  • Apache Ignite 中 WHERE 子句中的子查询(Subqueries in WHERE Clause)的执行方式
  • Android 中 实现日期选择功能(DatePickerDialog/MaterialDatePicker)