Vue3 + VueOffice 实现文档在线预览(本地文件版)
·
1. 项目概述
本项目基于 Vue3 和 VueOffice 系列组件,实现了一个简洁的文档在线预览功能。用户可以在前端直接预览本地服务器上的 PDF、Word、PPT、Excel 和 TXT 文件,无需下载或依赖外部服务。
核心特性:
- 支持 PDF、DOCX、PPTX、XLSX、TXT 五种常见格式。
- 使用
@vue-office官方组件,渲染效果好。 - 纯前端实现,文件需预先放置在服务器指定目录。
- 路由跳转,结构清晰。
2. 项目目录结构
vue-project/
├── public/ # 静态资源目录
│ └── files/ # 存放预览文件
│ ├── a.docx
│ ├── a.pptx
│ ├── a.xlsx
│ ├── a.txt
│ └── c.pdf
├── src/
│ ├── views/ # 页面组件
│ │ ├── HomeView.vue # 首页
│ │ └── FilePreview.vue # 预览页
│ ├── router/
│ │ └── index.js # 路由配置
│ ├── App.vue # 根组件
│ └── main.js # 应用入口
├── index.html
├── package.json # 项目依赖
└── vite.config.js # Vite 配置
关键目录说明:
public/files/:所有用于预览的示例文件需放在此目录,Vite 开发服务器会将其映射到根路径/files/。src/views/:两个页面组件,分别对应首页和预览页。src/router/index.js:定义了两个路由:/(首页)和/preview(预览页)。
3. 核心代码解析
3.1 路由配置 (src/router/index.js)
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
import FilePreview from '../views/FilePreview.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/preview',
name: 'preview',
component: FilePreview
}
]
})
export default router
- 使用
createWebHistory模式,URL 更友好。 - 定义了两个路由,分别指向首页和预览页组件。
3.2 首页组件 (src/views/HomeView.vue)
<template>
<div style="padding: 40px;">
<h1>Vue3 文档预览演示</h1>
<p>点击按钮进入预览页面:</p>
<router-link to="/preview">
<button style="padding: 10px 20px; font-size: 16px; cursor: pointer;">
进入文档预览
</button>
</router-link>
</div>
</template>
- 一个简单的引导页,通过
<router-link>跳转到/preview。
3.3 预览页组件 (src/views/FilePreview.vue)
这是核心功能页面,包含文件类型切换和预览区域。
<template>
<div style="padding: 20px;">
<h2>Vue3 文档在线预览(本地文件版)</h2>
<div style="margin: 10px 0; flex-wrap: wrap; display: flex; gap: 10px;">
<button @click="showPDF">预览 PDF</button>
<button @click="showWord">预览 Word</button>
<button @click="showPPT">预览 PPT</button>
<button @click="showExcel">预览 Excel</button>
<button @click="showTxt">预览 TXT</button>
</div>
<div style="border:1px solid #ccc; height: 700px; margin-top:20px; padding:10px; overflow:auto;">
<!-- PDF -->
<vue-office-pdf v-if="fileType === 'pdf'" :src="fileUrl" style="height:100%;" />
<!-- Word -->
<vue-office-docx v-else-if="fileType === 'docx'" :src="fileUrl" style="height:100%;" />
<!-- PPT -->
<vue-office-pptx v-else-if="fileType === 'pptx'" :src="fileUrl" style="height:100%;" />
<!-- Excel -->
<vue-office-excel v-else-if="fileType === 'xlsx'" :src="fileUrl" style="height:100%;" />
<!-- TXT 文本预览 -->
<pre v-else-if="fileType === 'txt'" style="margin:0; font-size:14px; white-space: pre-wrap;">{{ txtContent }}</pre>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
// 引入组件
import VueOfficePdf from '@vue-office/pdf'
import VueOfficeDocx from '@vue-office/docx'
import VueOfficePptx from '@vue-office/pptx'
import VueOfficeExcel from '@vue-office/excel'
// 文件类型 & 地址
const fileType = ref('')
const fileUrl = ref('')
const txtContent = ref('') // TXT 内容
// track any blob URL we create so we can revoke it when switching files
let currentBlobUrl = null
// NOTE: Do NOT keep sensitive tokens in front-end code. Use a backend proxy that adds the Authorization header.
function setFile(type, url, isBlob = false) {
// revoke previous blob URL if any
if (currentBlobUrl && currentBlobUrl !== url) {
try { URL.revokeObjectURL(currentBlobUrl) } catch (e) { /* ignore */ }
currentBlobUrl = null
}
fileType.value = type
fileUrl.value = url
if (isBlob) currentBlobUrl = url
}
// 预览 PDF
const showPDF = () => {
setFile('pdf', '/files/test.pdf')
}
// 预览 Word
// Fetch the DOCX via a local backend proxy which injects the Authorization header.
// Run a proxy (example: http://localhost:3000/proxy?url=<remoteUrl>) that holds the token.
const showWord = async () => {'/files/docx.pptx')
}
// 预览 PPT
const showPPT = () => {
setFile('pptx', '/files/test.pptx')
}
// 预览 Excel
const showExcel = () => {
setFile('xlsx', '/files/test.xlsx')
}
// 预览 TXT
const showTxt = async () => {
fileType.value = 'txt'
try {
const res = await fetch('/files/test.txt')
txtContent.value = await res.text()
} catch (e) {
txtContent.value = 'TXT 文件加载失败'
}
}
</script>
- 预览方法:每个按钮对应一个方法,设置
fileType和fileUrl。TXT 文件额外使用fetch获取文本内容。
3.4 根组件 (src/App.vue)
<template>
<router-view />
</template>
- 仅作为路由视图的容器。
4. 依赖配置 (package.json)
完整的 package.json 配置文件如下:
{
"name": "vue-project",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"test:unit": "vitest",
"format": "oxfmt src/"
},
"dependencies": {
"@vue-office/docx": "^1.6.3",
"@vue-office/excel": "^1.7.14",
"@vue-office/pdf": "^2.0.10",
"@vue-office/pptx": "^1.0.1",
"jszip": "^3.10.1",
"mammoth": "^1.12.0",
"vue": "^3.5.32",
"vue-router": "^5.0.4"
},
"devDependencies": {
"@vitejs/plugin-vue": "^6.0.6",
"@vue/test-utils": "^2.4.6",
"jsdom": "^29.0.2",
"oxfmt": "^0.45.0",
"vite": "^8.0.8",
"vite-plugin-vue-devtools": "^8.1.1",
"vitest": "^4.1.4"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
}
关键依赖说明:
"@vue-office/docx": "^1.6.3":Word 文档预览组件。"@vue-office/excel": "^1.7.14":Excel 预览组件。"@vue-office/pdf": "^2.0.10":PDF 预览组件。"@vue-office/pptx": "^1.0.1":PPT 预览组件。"vue": "^3.5.32":Vue3 核心。"vue-router": "^5.0.4":路由管理。"jszip": "^3.10.1"、"mammoth": "^1.12.0":VueOffice 内部处理 Office 文件所需。- 开发依赖:包含 Vite、Vue 插件、测试工具等,用于构建和开发。
- Node 版本:要求 Node.js 20.19.0 或 >=22.12.0。
5. 运行与部署
5.1 本地开发
- 安装依赖:
npm install - 启动开发服务器:
npm run dev - 访问
http://localhost:5173(默认端口)。
5.2 文件准备
将你的示例文件(如 a.docx, c.pdf 等)放入 public/files/ 目录。代码中通过 /files/ 路径访问。
5.3 构建生产版本
运行 npm run build,生成的文件在 dist 目录。需要确保服务器能正确提供 dist/files/ 下的静态文件。
6. 注意事项
- 文件路径:
fileUrl使用/files/xxx形式,对应public/files/xxx。生产环境需根据实际部署调整。 - 文件大小:VueOffice 组件在前端解析文件,过大文件可能导致浏览器内存不足或加载缓慢。
- 浏览器兼容:部分格式(如 PPTX)依赖较新的浏览器 API。
- 安全:本项目仅预览本地静态文件,不支持用户上传。如需上传预览,需自行实现文件上传和服务器端安全校验。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)