前端解决方案 - office 系列文件预览
简介微软 Office Web Viewer前端实现 pdf 预览本地选择远程请求 docx 预览本地选择远程请求 xlsx 预览本地选择远程请求 vue-office 组件pdf预览docx预览xlsx预览
简介
如果遇到文档管理类的业务功能,会出现需要在线预览的业务需求,合同文件、发票文件等业务同样需要文件的在线预览。
本文围绕以下解决方案展开:
微软 Office Web Viewer
pdfjs
docx-preview
xlsx
第三方封装组件
微软 Office Web Viewer
Office Web Viewer 是由微软提供的一项免费服务,用户不需要安装 Office 软件,直接通过浏览器在线预览 docx、xlsx、pptx 文件。
Office Web Viewer 的服务链接为:
https://view.officeapps.live.com/op/view.aspx?src=[文件链接]
其中 [文件链接] 是需要预览文件的在线地址,按需替换成自己的文件链接即可。
预览 docx
预览 xlsx
预览 pptx
注意
1、文件会传输到微软的服务器上,因此可能会涉及到文件隐私。
2、不支持 pdf 预览。
适用场景
用于公网展示的文件预览,如某公告文件在线预览,能快速实现需求。支持 docx、xlsx、pptx 文件,用于无需下载文件直接在线预览,适用于分享查看。前端实现
出于通用性考虑,通过 encodeURIComponent 对特殊字符进行编码
<script setup lang="ts">import { ref } from 'vue'// 预览地址const officeUrl = ref('')// 资源地址const docx = 'https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/solution/demo.docx'const xlsx = 'https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/solution/demo.xlsx'const pptx = 'https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/solution/demo.pptx'const pdf = 'https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/solution/demo.pdf'// 使用微软 Office Web Viewer 服务预览 office 文件const previewOffice = (url: string) => { // 考虑到特殊字符,通过 encodeURIComponent 处理一下 url officeUrl.value = `https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(url)}`}// 复制分享地址const copyToClipboard = async (text: string) => { await navigator.clipboard.writeText(text) alert('复制成功')}</script><template> <div class="container"> <div class="btns"> <!-- 微软 Office Web Viewer 服务 --> <button @click="previewOffice(docx)">预览docx</button> <button @click="previewOffice(xlsx)">预览xlsx</button> <button @click="previewOffice(pptx)">预览pptx</button> <!-- pdf 直接预览 --> <button @click="officeUrl = pdf">预览pdf</button> <!-- 复制分享地址 --> <button class="copy-btn" v-if="officeUrl" @click="copyToClipboard(officeUrl)"> 复制分享地址 </button> </div> <!-- 通过 iframe 嵌入 --> <iframe class="previewOffice" :src="officeUrl"></iframe> </div></template><style lang="scss">body { margin: 0;}.container { width: 100vw; height: 100vh; display: flex; flex-direction: column; .previewOffice { flex: 1; } .copy-btn { background-color: #070; color: #fff; }}</style>
pdf 预览
通过 PDF.js 加载 PDF 文件,渲染到 Canvas 上。
安装依赖 npm install pdfjs-dist设置 workerSrc 的值官方教程
npm install pdfjs-dist
业务场景
渲染 pdf 的需求较为常见,如预览电子发票,合同,学术论文等。
本地选择
<script setup lang="ts">import { ref } from 'vue'import * as pdfjsLib from 'pdfjs-dist'// 设置 workerSrc 的值,cdn 远程加载pdfjsLib.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjsLib.version}/pdf.worker.js`const canvasRef = ref<HTMLCanvasElement>()const previewPdf = async (event: Event) => { // 获取文件 const file = (event.target as HTMLInputElement).files?.[0] // 获取 canvas const canvas = canvasRef.value if (file && canvas) { const ctx = canvas.getContext('2d') if (!ctx) return const data = await file.arrayBuffer() pdfjsLib.getDocument({ data }).promise.then((pdf) => { pdf.getPage(1).then((page) => { const viewport = page.getViewport({ scale: 1.5 }) canvas.width = viewport.width canvas.height = viewport.height page.render({ canvasContext: ctx, viewport }) }) }) }}</script><template> <!-- pdf 预览 --> <input type="file" accept=".pdf" @change="previewPdf" /> <br /> <canvas ref="canvasRef"></canvas></template>
远程请求
<script setup lang="ts">import * as pdfjsLib from 'pdfjs-dist'import { ref } from 'vue'import axios from 'axios'// 设置 workerSrc 的值,cdn 远程加载pdfjsLib.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjsLib.version}/pdf.worker.js`const canvasRef = ref<HTMLCanvasElement>()const file = ref()const getFile = async () => { const res = await axios({ method: 'get', url: 'https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/solution/demo.pdf', responseType: 'arraybuffer', }) file.value = res.data}const previewFile = async () => { await getFile() const canvas = canvasRef.value if (file.value && canvas) { const ctx = canvas.getContext('2d') if (!ctx) return const data = new Uint8Array(file.value) pdfjsLib.getDocument({ data }).promise.then((pdf) => { pdf.getPage(1).then((page) => { const viewport = page.getViewport({ scale: 1.5 }) canvas.width = viewport.width canvas.height = viewport.height page.render({ canvasContext: ctx, viewport }) }) }) }}</script><template> <button @click="previewFile">获取文档</button> <br /> <!-- pdf 预览容器 --> <canvas ref="canvasRef"></canvas></template>
docx 预览
通过 docx-preview 加载 docx 文件。
安装依赖调用 renderAsync 方法来渲染文档官方文档
npm install docx-preview
本地选择
<script setup lang="ts">import { ref } from 'vue'import { defaultOptions, renderAsync } from 'docx-preview'// 定义一个 ref 来存储容器元素const container = ref<HTMLElement>()// 定义一个异步函数 previewFile 来预览文档const previewFile = async (event: Event) => { // 获取上传的文件 const file = (event.target as HTMLInputElement).files?.[0] if (file && container.value) { // 将文件转换为 ArrayBuffer const arrayBuffer = await file.arrayBuffer() // 调用 renderAsync 方法来渲染文档 await renderAsync(arrayBuffer, container.value, undefined, { ...defaultOptions, className: 'docx', inWrapper: true, ignoreWidth: false, ignoreHeight: false, ignoreFonts: false, breakPages: true, ignoreLastRenderedPageBreak: true, experimental: false, trimXmlDeclaration: true, debug: false, }) }}</script><template> <div> <!-- 添加一个文件上传的 input 元素,绑定 change 事件到 previewFile 函数 --> <input type="file" accept=".docx" @change="previewFile" /> <!-- 添加一个 div 元素,通过 ref 绑定到 container 变量 --> <div ref="container"></div> </div></template>
远程请求
<script setup lang="ts">import { ref } from 'vue'import { defaultOptions, renderAsync } from 'docx-preview'import axios from 'axios'// 定义一个 ref 来存储容器元素const container = ref<HTMLElement>()const fileRef = ref()const getFile = async () => { const res = await axios({ method: 'get', url: 'https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/solution/demo.docx', // 返回类型为 arraybuffer responseType: 'arraybuffer', }) fileRef.value = res.data}// 定义一个异步函数 previewFile 来预览文档const previewFile = async () => { // 获取文档 await getFile() // 获取 arraybuffer const file = fileRef.value if (file && container.value) { // 调用 renderAsync 方法来渲染文档 await renderAsync(file, container.value, undefined, { ...defaultOptions, className: 'docx', inWrapper: true, ignoreWidth: false, ignoreHeight: false, ignoreFonts: false, breakPages: true, ignoreLastRenderedPageBreak: true, experimental: false, trimXmlDeclaration: true, debug: false, }) }}</script><template> <button @click="previewFile">获取文档</button> <br /> <!-- 添加一个 div 元素,通过 ref 绑定到 container 变量 --> <div ref="container"></div></template>
xlsx 预览
通过 xlsx 加载 xlsx 文件。
安装依赖调用相关方法获取 excel 文件数据官方教程
npm install xlsx
本地选择
<script setup lang="ts">import { ref } from 'vue'import { read, utils } from 'xlsx'// 本地选择文件const rows = ref<any>([])const previewFile = async (event: Event) => { // 获取上传的文件 const file = (event.target as HTMLInputElement).files?.[0] if (file) { // 将文件转换为 ArrayBuffer const arrayBuffer = await file.arrayBuffer() // 读取 Sheets const sheet = read(arrayBuffer).Sheets /* 渲染数据 */ rows.value = utils.sheet_to_json(sheet['Data']) }}</script><template> <input type="file" accept=".xlsx" ref="fileInput" @change="previewFile" /> <table> <thead> <th>Name</th> <th>Index</th> </thead> <tbody> <tr v-for="(item, index) in rows" :key="index"> <td>{{ item.Name }}</td> <td>{{ item.Index }}</td> </tr> </tbody> </table></template>
远程请求
<script setup lang="ts">import axios from 'axios'import { ref } from 'vue'import { read, utils } from 'xlsx'const getFile = async () => { const res = await axios({ method: 'get', url: 'https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/solution/demo.xlsx', // 返回类型为 arraybuffer responseType: 'arraybuffer', }) return res.data}const rows = ref<any>([])const previewFile = async () => { const arrayBuffer = await getFile() if (arrayBuffer) { // 读取 Sheets const sheet = read(arrayBuffer).Sheets /* 渲染数据 */ rows.value = utils.sheet_to_json(sheet['Data']) }}</script><template> <button @click="previewFile">获取文档</button> <br /> <table> <thead> <th>Name</th> <th>Index</th> </thead> <tbody> <tr v-for="(item, index) in rows" :key="index"> <td>{{ item.Name }}</td> <td>{{ item.Index }}</td> </tr> </tbody> </table></template>
vue-office 组件
支持多种文件(docx、excel、pdf)预览的 vue 组件库。
同时支持 vue2/3使用简单支持本地文件支持远程地址官方文档
pdf预览
安装依赖
npm install @vue-office/pdf
导入并使用
<script setup lang="ts">// 引入 VueOffice 组件import VueOfficePdf from '@vue-office/pdf'import { ref } from 'vue'// 设置文档网络地址,可以是本地文件const src = ref()// 本地预览const previewFile = async (event: Event) => { src.value = (event.target as HTMLInputElement).files?.[0]}// 请求预览const getFile = () => { src.value = 'https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/solution/demo.pdf'}</script><template> <button @click="getFile">获取远程</button> <input type="file" accept=".pdf" @change="previewFile" /> <vue-office-pdf :src="src" style="height: 100vh" /></template>
docx预览
安装依赖
npm install @vue-office/docx
导入并使用
```vue<script setup lang="ts">// 引入 VueOffice 组件import VueOfficeDocx from '@vue-office/docx'// 引入相关样式import '@vue-office/docx/lib/index.css'import { ref } from 'vue'// 设置文档网络地址,可以是本地文件const src = ref()// 本地预览const previewFile = async (event: Event) => { src.value = (event.target as HTMLInputElement).files?.[0]}// 请求预览const getFile = () => { src.value = 'https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/solution/demo.docx'}</script><template> <button @click="getFile">获取远程</button> <input type="file" accept=".docx" @change="previewFile" /> <vue-office-docx :src="src" style="height: 100vh" /></template>
xlsx预览
安装依赖
npm install @vue-office/excel
导入并使用
<script setup lang="ts">// 引入 VueOffice 组件import VueOfficeExcel from '@vue-office/excel'// 引入相关样式import '@vue-office/excel/lib/index.css'import { ref } from 'vue'// 设置文档网络地址,可以是本地文件const src = ref()// 本地预览const previewFile = async (event: Event) => { src.value = (event.target as HTMLInputElement).files?.[0]}// 请求预览const getFile = () => { src.value = 'https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/solution/demo.xlsx'}</script><template> <button @click="getFile">获取远程</button> <input type="file" accept=".xlsx" @change="previewFile" /> <vue-office-excel :src="src" style="height: 100vh" /></template>