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

st646889325 2024-10-14 11:03:01 阅读 99

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

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">code>

<div class="btns">code>

<!-- 微软 Office Web Viewer 服务 -->

<button @click="previewOffice(docx)">预览docx</button>code>

<button @click="previewOffice(xlsx)">预览xlsx</button>code>

<button @click="previewOffice(pptx)">预览pptx</button>code>

<!-- pdf 直接预览 -->

<button @click="officeUrl = pdf">预览pdf</button>code>

<!-- 复制分享地址 -->

<button class="copy-btn" v-if="officeUrl" @click="copyToClipboard(officeUrl)">code>

复制分享地址

</button>

</div>

<!-- 通过 iframe 嵌入 -->

<iframe class="previewOffice" :src="officeUrl"></iframe>code>

</div>

</template>

<style lang="scss">code>

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">code>

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" />code>

<br />

<canvas ref="canvasRef"></canvas>code>

</template>

远程请求

<script setup lang="ts">code>

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>code>

<br />

<!-- pdf 预览容器 -->

<canvas ref="canvasRef"></canvas>code>

</template>

docx 预览

通过 docx-preview 加载 docx 文件。

安装依赖调用 renderAsync 方法来渲染文档

官方文档

npm install docx-preview

本地选择

<script setup lang="ts">code>

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" />code>

<!-- 添加一个 div 元素,通过 ref 绑定到 container 变量 -->

<div ref="container"></div>code>

</div>

</template>

远程请求

<script setup lang="ts">code>

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>code>

<br />

<!-- 添加一个 div 元素,通过 ref 绑定到 container 变量 -->

<div ref="container"></div>code>

</template>

xlsx 预览

通过 xlsx 加载 xlsx 文件。

安装依赖调用相关方法获取 excel 文件数据

官方教程

npm install xlsx

本地选择

<script setup lang="ts">code>

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" />code>

<table>

<thead>

<th>Name</th>

<th>Index</th>

</thead>

<tbody>

<tr v-for="(item, index) in rows" :key="index">code>

<td>{ -- -->{ item.Name }}</td>

<td>{ { item.Index }}</td>

</tr>

</tbody>

</table>

</template>

远程请求

<script setup lang="ts">code>

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>code>

<br />

<table>

<thead>

<th>Name</th>

<th>Index</th>

</thead>

<tbody>

<tr v-for="(item, index) in rows" :key="index">code>

<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">code>

// 引入 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>code>

<input type="file" accept=".pdf" @change="previewFile" />code>

<vue-office-pdf :src="src" style="height: 100vh" />code>

</template>

docx预览

安装依赖

npm install @vue-office/docx

导入并使用

```vue

<script setup lang="ts">code>

// 引入 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>code>

<input type="file" accept=".docx" @change="previewFile" />code>

<vue-office-docx :src="src" style="height: 100vh" />code>

</template>

xlsx预览

安装依赖

npm install @vue-office/excel

导入并使用

<script setup lang="ts">code>

// 引入 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>code>

<input type="file" accept=".xlsx" @change="previewFile" />code>

<vue-office-excel :src="src" style="height: 100vh" />code>

</template>



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。