ToB企服应用市场:ToB评测及商务社交产业平台

标题: 前端解决方案 - office 系列文件预览 [打印本页]

作者: 伤心客    时间: 2024-11-30 21:33
标题: 前端解决方案 - office 系列文件预览
简介

假如遇到文档管理类的业务功能,会出现需要在线预览的业务需求,条约文件、发票文件等业务同样需要文件的在线预览。
本文围绕以下解决方案睁开:
微软 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 预览。
适用场景

前端实现

出于通用性考虑,通过 encodeURIComponent 对特殊字符进行编码
  1. <script setup lang="ts">
  2. import { ref } from 'vue'
  3. // 预览地址
  4. const officeUrl = ref('')
  5. // 资源地址
  6. const docx = 'https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/solution/demo.docx'
  7. const xlsx = 'https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/solution/demo.xlsx'
  8. const pptx = 'https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/solution/demo.pptx'
  9. const pdf = 'https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/solution/demo.pdf'
  10. // 使用微软 Office Web Viewer 服务预览 office 文件
  11. const previewOffice = (url: string) => {
  12.   // 考虑到特殊字符,通过 encodeURIComponent 处理一下 url
  13.   officeUrl.value = `https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(url)}`
  14. }
  15. // 复制分享地址
  16. const copyToClipboard = async (text: string) => {
  17.   await navigator.clipboard.writeText(text)
  18.   alert('复制成功')
  19. }
  20. </script>
  21. <template>
  22.   <div class="container">
  23.     <div class="btns">
  24.       <!-- 微软 Office Web Viewer 服务 -->
  25.       <button @click="previewOffice(docx)">预览docx</button>
  26.       <button @click="previewOffice(xlsx)">预览xlsx</button>
  27.       <button @click="previewOffice(pptx)">预览pptx</button>
  28.       <!-- pdf 直接预览 -->
  29.       <button @click="officeUrl = pdf">预览pdf</button>
  30.       <!-- 复制分享地址 -->
  31.       <button class="copy-btn" v-if="officeUrl" @click="copyToClipboard(officeUrl)">
  32.         复制分享地址
  33.       </button>
  34.     </div>
  35.     <!-- 通过 iframe 嵌入 -->
  36.     <iframe class="previewOffice" :src="officeUrl"></iframe>
  37.   </div>
  38. </template>
  39. <style lang="scss">
  40. body {
  41.   margin: 0;
  42. }
  43. .container {
  44.   width: 100vw;
  45.   height: 100vh;
  46.   display: flex;
  47.   flex-direction: column;
  48.   .previewOffice {
  49.     flex: 1;
  50.   }
  51.   .copy-btn {
  52.     background-color: #070;
  53.     color: #fff;
  54.   }
  55. }
  56. </style>
复制代码
pdf 预览

通过 PDF.js 加载 PDF 文件,渲染到 Canvas 上。

官方教程
   npm install pdfjs-dist
  业务场景
渲染 pdf 的需求较为常见,如预览电子发票,条约,学术论文等。
本地选择

  1. <script setup lang="ts">
  2. import { ref } from 'vue'
  3. import * as pdfjsLib from 'pdfjs-dist'
  4. // 设置 workerSrc 的值,cdn 远程加载
  5. pdfjsLib.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjsLib.version}/pdf.worker.js`
  6. const canvasRef = ref<HTMLCanvasElement>()
  7. const previewPdf = async (event: Event) => {
  8.   // 获取文件
  9.   const file = (event.target as HTMLInputElement).files?.[0]
  10.   // 获取 canvas
  11.   const canvas = canvasRef.value
  12.   if (file && canvas) {
  13.     const ctx = canvas.getContext('2d')
  14.     if (!ctx) return
  15.     const data = await file.arrayBuffer()
  16.     pdfjsLib.getDocument({ data }).promise.then((pdf) => {
  17.       pdf.getPage(1).then((page) => {
  18.         const viewport = page.getViewport({ scale: 1.5 })
  19.         canvas.width = viewport.width
  20.         canvas.height = viewport.height
  21.         page.render({ canvasContext: ctx, viewport })
  22.       })
  23.     })
  24.   }
  25. }
  26. </script>
  27. <template>
  28.   <!-- pdf 预览 -->
  29.   <input type="file" accept=".pdf" @change="previewPdf" />
  30.   <br />
  31.   <canvas ref="canvasRef"></canvas>
  32. </template>
复制代码
远程请求

  1. <script setup lang="ts">
  2. import * as pdfjsLib from 'pdfjs-dist'
  3. import { ref } from 'vue'
  4. import axios from 'axios'
  5. // 设置 workerSrc 的值,cdn 远程加载
  6. pdfjsLib.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjsLib.version}/pdf.worker.js`
  7. const canvasRef = ref<HTMLCanvasElement>()
  8. const file = ref()
  9. const getFile = async () => {
  10.   const res = await axios({
  11.     method: 'get',
  12.     url: 'https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/solution/demo.pdf',
  13.     responseType: 'arraybuffer',
  14.   })
  15.   file.value = res.data
  16. }
  17. const previewFile = async () => {
  18.   await getFile()
  19.   const canvas = canvasRef.value
  20.   if (file.value && canvas) {
  21.     const ctx = canvas.getContext('2d')
  22.     if (!ctx) return
  23.     const data = new Uint8Array(file.value)
  24.     pdfjsLib.getDocument({ data }).promise.then((pdf) => {
  25.       pdf.getPage(1).then((page) => {
  26.         const viewport = page.getViewport({ scale: 1.5 })
  27.         canvas.width = viewport.width
  28.         canvas.height = viewport.height
  29.         page.render({ canvasContext: ctx, viewport })
  30.       })
  31.     })
  32.   }
  33. }
  34. </script>
  35. <template>
  36.   <button @click="previewFile">获取文档</button>
  37.   <br />
  38.   <!-- pdf 预览容器 -->
  39.   <canvas ref="canvasRef"></canvas>
  40. </template>
复制代码
docx 预览

通过 docx-preview 加载 docx 文件。

官方文档
   npm install docx-preview
  本地选择

  1. <script setup lang="ts">
  2. import { ref } from 'vue'
  3. import { defaultOptions, renderAsync } from 'docx-preview'
  4. // 定义一个 ref 来存储容器元素
  5. const container = ref<HTMLElement>()
  6. // 定义一个异步函数 previewFile 来预览文档
  7. const previewFile = async (event: Event) => {
  8.   // 获取上传的文件
  9.   const file = (event.target as HTMLInputElement).files?.[0]
  10.   if (file && container.value) {
  11.     // 将文件转换为 ArrayBuffer
  12.     const arrayBuffer = await file.arrayBuffer()
  13.     // 调用 renderAsync 方法来渲染文档
  14.     await renderAsync(arrayBuffer, container.value, undefined, {
  15.       ...defaultOptions,
  16.       className: 'docx',
  17.       inWrapper: true,
  18.       ignoreWidth: false,
  19.       ignoreHeight: false,
  20.       ignoreFonts: false,
  21.       breakPages: true,
  22.       ignoreLastRenderedPageBreak: true,
  23.       experimental: false,
  24.       trimXmlDeclaration: true,
  25.       debug: false,
  26.     })
  27.   }
  28. }
  29. </script>
  30. <template>
  31.   <div>
  32.     <!-- 添加一个文件上传的 input 元素,绑定 change 事件到 previewFile 函数 -->
  33.     <input type="file" accept=".docx" @change="previewFile" />
  34.     <!-- 添加一个 div 元素,通过 ref 绑定到 container 变量 -->
  35.     <div ref="container"></div>
  36.   </div>
  37. </template>
复制代码
远程请求

  1. <script setup lang="ts">
  2. import { ref } from 'vue'
  3. import { defaultOptions, renderAsync } from 'docx-preview'
  4. import axios from 'axios'
  5. // 定义一个 ref 来存储容器元素
  6. const container = ref<HTMLElement>()
  7. const fileRef = ref()
  8. const getFile = async () => {
  9.   const res = await axios({
  10.     method: 'get',
  11.     url: 'https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/solution/demo.docx',
  12.     // 返回类型为 arraybuffer
  13.     responseType: 'arraybuffer',
  14.   })
  15.   fileRef.value = res.data
  16. }
  17. // 定义一个异步函数 previewFile 来预览文档
  18. const previewFile = async () => {
  19.   // 获取文档
  20.   await getFile()
  21.   // 获取 arraybuffer
  22.   const file = fileRef.value
  23.   if (file && container.value) {
  24.     // 调用 renderAsync 方法来渲染文档
  25.     await renderAsync(file, container.value, undefined, {
  26.       ...defaultOptions,
  27.       className: 'docx',
  28.       inWrapper: true,
  29.       ignoreWidth: false,
  30.       ignoreHeight: false,
  31.       ignoreFonts: false,
  32.       breakPages: true,
  33.       ignoreLastRenderedPageBreak: true,
  34.       experimental: false,
  35.       trimXmlDeclaration: true,
  36.       debug: false,
  37.     })
  38.   }
  39. }
  40. </script>
  41. <template>
  42.   <button @click="previewFile">获取文档</button>
  43.   <br />
  44.   <!-- 添加一个 div 元素,通过 ref 绑定到 container 变量 -->
  45.   <div ref="container"></div>
  46. </template>
复制代码
xlsx 预览

通过 xlsx 加载 xlsx 文件。

官方教程
   npm install xlsx
  本地选择

  1. <script setup lang="ts">
  2. import { ref } from 'vue'
  3. import { read, utils } from 'xlsx'
  4. // 本地选择文件
  5. const rows = ref<any>([])
  6. const previewFile = async (event: Event) => {
  7.   // 获取上传的文件
  8.   const file = (event.target as HTMLInputElement).files?.[0]
  9.   if (file) {
  10.     // 将文件转换为 ArrayBuffer
  11.     const arrayBuffer = await file.arrayBuffer()
  12.     // 读取 Sheets
  13.     const sheet = read(arrayBuffer).Sheets
  14.     /* 渲染数据 */
  15.     rows.value = utils.sheet_to_json(sheet['Data'])
  16.   }
  17. }
  18. </script>
  19. <template>
  20.   <input type="file" accept=".xlsx" ref="fileInput" @change="previewFile" />
  21.   <table>
  22.     <thead>
  23.       <th>Name</th>
  24.       <th>Index</th>
  25.     </thead>
  26.     <tbody>
  27.       <tr v-for="(item, index) in rows" :key="index">
  28.         <td>{{ item.Name }}</td>
  29.         <td>{{ item.Index }}</td>
  30.       </tr>
  31.     </tbody>
  32.   </table>
  33. </template>
复制代码
远程请求

  1. <script setup lang="ts">
  2. import axios from 'axios'
  3. import { ref } from 'vue'
  4. import { read, utils } from 'xlsx'
  5. const getFile = async () => {
  6.   const res = await axios({
  7.     method: 'get',
  8.     url: 'https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/solution/demo.xlsx',
  9.     // 返回类型为 arraybuffer
  10.     responseType: 'arraybuffer',
  11.   })
  12.   return res.data
  13. }
  14. const rows = ref<any>([])
  15. const previewFile = async () => {
  16.   const arrayBuffer = await getFile()
  17.   if (arrayBuffer) {
  18.     // 读取 Sheets
  19.     const sheet = read(arrayBuffer).Sheets
  20.     /* 渲染数据 */
  21.     rows.value = utils.sheet_to_json(sheet['Data'])
  22.   }
  23. }
  24. </script>
  25. <template>
  26.   <button @click="previewFile">获取文档</button>
  27.   <br />
  28.   <table>
  29.     <thead>
  30.       <th>Name</th>
  31.       <th>Index</th>
  32.     </thead>
  33.     <tbody>
  34.       <tr v-for="(item, index) in rows" :key="index">
  35.         <td>{{ item.Name }}</td>
  36.         <td>{{ item.Index }}</td>
  37.       </tr>
  38.     </tbody>
  39.   </table>
  40. </template>
复制代码
vue-office 组件

支持多种文件(docx、excel、pdf)预览的 vue 组件库。

官方文档
pdf预览

安装依靠
   npm install @vue-office/pdf
  导入并利用
  1. <script setup lang="ts">
  2. // 引入 VueOffice 组件
  3. import VueOfficePdf from '@vue-office/pdf'
  4. import { ref } from 'vue'
  5. // 设置文档网络地址,可以是本地文件
  6. const src = ref()
  7. // 本地预览
  8. const previewFile = async (event: Event) => {
  9.   src.value = (event.target as HTMLInputElement).files?.[0]
  10. }
  11. // 请求预览
  12. const getFile = () => {
  13.   src.value = 'https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/solution/demo.pdf'
  14. }
  15. </script>
  16. <template>
  17.   <button @click="getFile">获取远程</button>
  18.   <input type="file" accept=".pdf" @change="previewFile" />
  19.   <vue-office-pdf :src="src" style="height: 100vh" />
  20. </template>
复制代码
docx预览

安装依靠
   npm install @vue-office/docx
  导入并利用
  1. ```vue
  2. <script setup lang="ts">
  3. // 引入 VueOffice 组件
  4. import VueOfficeDocx from '@vue-office/docx'
  5. // 引入相关样式
  6. import '@vue-office/docx/lib/index.css'
  7. import { ref } from 'vue'
  8. // 设置文档网络地址,可以是本地文件
  9. const src = ref()
  10. // 本地预览
  11. const previewFile = async (event: Event) => {
  12.   src.value = (event.target as HTMLInputElement).files?.[0]
  13. }
  14. // 请求预览
  15. const getFile = () => {
  16.   src.value = 'https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/solution/demo.docx'
  17. }
  18. </script>
  19. <template>
  20.   <button @click="getFile">获取远程</button>
  21.   <input type="file" accept=".docx" @change="previewFile" />
  22.   <vue-office-docx :src="src" style="height: 100vh" />
  23. </template>
复制代码
xlsx预览

安装依靠
   npm install @vue-office/excel
  导入并利用
  1. <script setup lang="ts">
  2. // 引入 VueOffice 组件
  3. import VueOfficeExcel from '@vue-office/excel'
  4. // 引入相关样式
  5. import '@vue-office/excel/lib/index.css'
  6. import { ref } from 'vue'
  7. // 设置文档网络地址,可以是本地文件
  8. const src = ref()
  9. // 本地预览
  10. const previewFile = async (event: Event) => {
  11.   src.value = (event.target as HTMLInputElement).files?.[0]
  12. }
  13. // 请求预览
  14. const getFile = () => {
  15.   src.value = 'https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/solution/demo.xlsx'
  16. }
  17. </script>
  18. <template>
  19.   <button @click="getFile">获取远程</button>
  20.   <input type="file" accept=".xlsx" @change="previewFile" />
  21.   <vue-office-excel :src="src" style="height: 100vh" />
  22. </template>
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4