在 Vue 中实现 PDF 文件预览并跳转新标签页,需根据 PDF 的来源(本地静态文件、远程 URL、接口返回的文件流)选择不同方案,以下是常见场景的完整实现:
一、场景 1:预览本地静态 PDF 文件(放在 public 目录)
如果 PDF 是项目内的静态资源(如 public/docs/test.pdf),可直接通过文件路径打开新标签页预览。
实现代码
vue
<template>
<el-button @click="openLocalPdf">预览本地 PDF</el-button>
</template>
<script>
export default {
methods: {
openLocalPdf() {
// public 目录下的文件可直接通过相对路径访问
const pdfPath = '/docs/test.pdf'
// 跳转新标签页打开
window.open(pdfPath, '_blank')
}
}
}
</script>
注意事项
- 静态 PDF 文件必须放在
public目录下(Vue CLI 项目),打包后会被复制到输出目录的根目录,可直接通过根路径访问。 - 若路径错误,会导致新标签页显示 404,需检查文件路径是否正确。
二、场景 2:预览远程 URL 对应的 PDF(如服务器上的 PDF)
如果 PDF 已部署在服务器,有公开的访问 URL,直接通过 window.open 打开该 URL 即可,浏览器会自动解析预览。
实现代码
vue
<template>
<el-button @click="openRemotePdf">预览远程 PDF</el-button>
</template>
<script>
export default {
methods: {
openRemotePdf() {
// 服务器上的 PDF 地址
const remotePdfUrl = 'https://example.com/files/report.pdf'
// 新标签页打开
window.open(remotePdfUrl, '_blank')
}
}
}
</script>
注意事项
- 确保远程 PDF URL 可访问(无跨域限制或权限拦截)。
- 若 URL 需携带权限参数(如 token),可直接拼在 URL 后(如
remotePdfUrl + '?token=' + localStorage.getItem('token'))。
三、场景 3:预览接口返回的 PDF 文件流(需携带请求头,如 Token)
如果 PDF 需通过接口动态获取(如需要用户权限验证),接口返回 blob 类型的文件流,需先请求接口获取 Blob,再构造临时 URL 打开新标签页。
步骤 1:封装接口请求(结合之前的 axios 配置)
在 src/api/file.js 中添加获取 PDF 流的接口:
javascript
import request from '@/utils/request'
export default {
// 获取 PDF 文件流
getPdfStream(params) {
return request({
url: '/api/file/export-pdf',
method: 'get',
params, // 接口参数(如报表 ID)
responseType: 'blob', // 关键:指定响应类型为 blob
headers: {
// 若需权限验证,携带 Token(根据项目实际情况调整)
Authorization: `Bearer ${localStorage.getItem('token')}`
}
})
}
}
步骤 2:组件中调用并打开新标签页
vue
<template>
<el-button @click="openPdfStream">预览接口返回的 PDF</el-button>
</template>
<script>
import api from '@/api'
export default {
methods: {
async openPdfStream() {
try {
// 1. 请求接口获取 PDF 流
const blob = await api.file.getPdfStream({ reportId: 123 })
// 2. 构造 Blob URL
const pdfUrl = URL.createObjectURL(
new Blob([blob], { type: 'application/pdf' }) // 指定 MIME 类型为 PDF
)
// 3. 新标签页打开预览
window.open(pdfUrl, '_blank')
// 4. 可选:页面卸载时释放 Blob URL,避免内存泄漏
this.$once('hook:beforeDestroy', () => {
URL.revokeObjectURL(pdfUrl)
})
} catch (error) {
console.error('获取 PDF 失败:', error)
this.$message.error('预览 PDF 失败,请重试')
}
}
}
}
</script>
四、场景 4:Electron + Vue 环境的特殊处理
由于你的项目是 Electron + Vue,Electron 渲染进程打开新窗口有两种方式,需注意窗口权限配置:
方式 1:用默认浏览器打开(推荐,避免 Electron 窗口兼容性问题)
javascript
// 引入 Electron 的 shell 模块(渲染进程需开启 Node 集成)
const { shell } = require('electron')
// 替换 window.open 为 shell.openExternal
openPdfStream() {
// ... 前面获取 pdfUrl 的逻辑不变
shell.openExternal(pdfUrl) // 用系统默认浏览器打开 PDF,兼容性更好
}
方式 2:用 Electron 新窗口打开
javascript
const { remote } = require('electron')
const BrowserWindow = remote.BrowserWindow
openPdfStream() {
// ... 前面获取 pdfUrl 的逻辑不变
// 创建新的 Electron 窗口
const pdfWindow = new BrowserWindow({
width: 1000,
height: 800,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
})
pdfWindow.loadURL(pdfUrl) // 加载 PDF 的 Blob URL
}
关键注意事项
-
Blob URL 内存泄漏 :通过
URL.createObjectURL生成的 URL 会占用内存,建议在组件卸载时用URL.revokeObjectURL释放。 -
浏览器兼容性 :大部分现代浏览器(Chrome、Edge、Firefox)支持直接预览 PDF,IE 需安装插件,若需兼容 IE 可使用
pdf.js库增强。 -
Electron 权限:若渲染进程无法使用
electron模块,需检查background.js中是否开启 Node 集成:javascript// background.js 中创建窗口时的配置 new BrowserWindow({ // ... 其他配置 webPreferences: { nodeIntegration: true, // 开启 Node 集成 contextIsolation: false // 关闭上下文隔离(Vue 2 项目常用) } })
扩展:使用 pdf.js 增强预览功能(可选)
如果需要更灵活的预览功能(如分页控制、批注),可集成 pdf.js 库,核心思路是通过 pdf.js 解析 Blob 或 URL,再渲染到页面中,同时支持跳转新标签页打开完整预览。