当前位置:首页 » 《随便一记》 » 正文

前端解决方案 - office 系列文件预览

0 人参与  2024年11月19日 16:01  分类 : 《随便一记》  评论

点击全文阅读


前端解决方案 - 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>

点击全文阅读


本文链接:http://m.zhangshiyu.com/post/188807.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1