Vue3实现常见附件的预览功能
作者:coding小虾米
前言
最近开发了一个建筑相关的移动端项目,其中有各种附件预览的功能。通过各种尝试,总结出了一些常用的文件预览方式。本文介绍vue3常用文件(pdf、word、excel、txt)的预览。
一、pdf预览
本文使用的pdf预览是通过 pdfjs-dist 插件,在 Vue3
使用的时候还是有一些坑。
首先通过 npm
安装插件
npm install --save pdfjs-dist
然后在页面中引入
const PDF = require('pdfjs-dist')
启动项目之后就会报错如下:
仔细查看报错信息,是插件中使用了 es11
的语法 ?.
然而当项目启动,插件中的代码没有经过编译,导致项目不能启动。解决方案是在项目中配置webpack
针对于这个插件进行编译。
修改项目根目录下 vue.config.js
,如果没有就创建一个,在文件中增加如下代码:
// vue.config.js module.exports = { // ... chainWebpack: config => { // ... config.module.rule('pdfjs-dist').test({ test: /\.js$/, include: path.join(__dirname, 'node_modules/pdfjs-dist') }).use('babel-loader').loader('babel-loader').options({ presets: ['@babel/preset-env'], plugins: ['@babel/plugin-proposal-optional-chaining'] }) } }
之后的错误
需要在引入 pdfjs-dist
之后配置 workerSrc
,但是引入 pdfjs-dist/build/pdf.worker.entry
之后浏览器还是有个警告:Warning: Setting up fake worker.
,经过各种原因查找,最终找到了一句描述:pdf.worker.js必须位于自己的文件中(而不是与pdf.js捆绑在一起)。否则它不能在服务工作线程中运行。
解决方式:将 pdfjs-dist/build/pdf.worker.js
复制一份放到项目 public
目录下。
pdf解析组件代码
通过 pdfjs-dist
加载pdf文件,获取到总页数将 canvas
遍历到页面上,然后编写一个递归函数通过 getPage
解析 pdf 的每一页将pdf内容渲染到 canvas
。以下示例就是封装了一个解析pdf组件,通过传递文件链接全屏渲染pdf。
<template> <div class="pdf"> <template v-for="item in pageNum" :key="item"> <canvas :id="`pdf-canvas-${item}`" class="pdf-page" /> </template> </div> </template> <script> import { reactive, toRefs, nextTick, watchEffect } from 'vue' const PDF = require('pdfjs-dist') PDF.GlobalWorkerOptions.workerSrc = '/pdf.worker.js' export default { name: 'DisplayPdf', props: { url: { type: String, default: '' } }, setup (props, { emit }) { const state = reactive({ pageNum: 0, pdfCtx: null }) watchEffect(() => { if (props.url) { resolvePdf(props.url) } }) const resolvePdf = (url) => { const loadingTask = PDF.getDocument(url) loadingTask.promise.then(pdf => { state.pdfCtx = pdf state.pageNum = pdf.numPages nextTick(() => { renderPdf() }) }) } const renderPdf = (num = 1) => { state.pdfCtx.getPage(num).then(page => { const canvas = document.getElementById(`pdf-canvas-${num}`) const ctx = canvas.getContext('2d') const viewport = page.getViewport({ scale: 1 }) // 画布大小,默认值是width:300px,height:150px canvas.height = viewport.height canvas.width = viewport.width // 画布的dom大小, 设置移动端,宽度设置铺满整个屏幕 const clientWidth = document.body.clientWidth canvas.style.width = clientWidth + 'px' // 根据pdf每页的宽高比例设置canvas的高度 canvas.style.height = clientWidth * (viewport.height / viewport.width) + 'px' page.render({ canvasContext: ctx, viewport }) if (num < state.pageNum) { renderPdf(num + 1) } else { emit('onRendered') } }) } return { ...toRefs(state) } } } </script>
二、txt文件预览
txt
的文件预览就比较简单了,因为没有样式,我们直接读取文件的内容,展示到页面即可。
需要注意的是,如果需要正常显示 txt
文件中的换行符需要在文本容器上加上样式:white-space: pre-wrap;
,或者将内容中所有的换行符替换成 <br>
使用 v-html
显示内容。
<template> <div class="txt" style="white-space: pre-wrap;">{{ txtContent }}</div> </template> <script> import { ref } from 'vue' import axios from 'axios' export default { name: 'PreviewTxt', setup () { const txtContent = ref('') const url = '/demo.txt' axios.get(url, { responseType: 'text' }).then(res => { txtContent.value = res.data }) return { txtContent } } } </script>
三、word预览
本文中使用的是 mammoth.js
,会忽略复杂样式,只是实现了简单内容预览,使用方式也很简单,通过http请求获取文件的 ArrayBuffer
,再使用 mammoth.convertToHtml
将内容转换成 html
。如果文件能够外网访问并且机密性不高,还是推荐使用 http://view.officeapps.live.com/op/view.aspx?src=文档url
的方式预览。
// npm install mammoth --save <template> <div class="word-container" v-html="doc" /> </template> <script> import { watchEffect, ref } from 'vue' import axios from 'axios' import mammoth from 'mammoth' export default { name: 'DisplayDocx', props: { url: { type: String, default: '' } }, setup (props) { const doc = ref('') const resolveDocx = async (url) => { const { data } = await axios.get(url, { responseType: 'arraybuffer' }) const res = await mammoth.convertToHtml({ arrayBuffer: data }) doc.value = res.value } watchEffect(() => { if (props.url) resolveDocx(props.url) }) return { doc } } } </script>
四、excel预览
excel预览是使用 xsls
插件,读取文件的某个 Sheet
中的内容,然后把内容转换成 json
我们自己用json渲染表格。
npm install xsls --save
读取出json内容如下,默认以第一行为 key。
也可以通过 sheet_to_json
第二个参数改变,如果传入 { header: 1 }
则返回每行为文件中的一行组成数组
示例代码
import xlsx from 'xlsx' import axios from 'axios' export default { name: 'PreviewExcel', async setup () { const url = '/demo.xlsx' const { data } = await axios.get(url, { responseType: 'arraybuffer' }) const ctx = xlsx.read(data, { type: 'array' }) const result = xlsx.utils.sheet_to_json(ctx.Sheets[ctx.SheetNames[0]], { header: 1 }) console.log(result) } }
以上就是Vue3实现常见附件的预览功能的详细内容,更多关于Vue3预览的资料请关注脚本之家其它相关文章!