简介
假如遇到文档管理类的业务功能,会出现需要在线预览的业务需求,条约文件、发票文件等业务同样需要文件的在线预览。
本文围绕以下解决方案睁开:
微软 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 文件。
官方教程
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>
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |