前端开发的 web 页面中常常需要上传附件,而针对附件预览我们往往都是直接下载打开,其实我们也可以提前预览让客户选择性下载,体验上肯定是更加友好的。当然了,不可避免的要借助一些第三方的库进行解析与渲染,主打的就是一个贯彻CV开发的理念。
一、Pdf
<div class="pdf-style">
<vue-pdf-embed
:source="pdfState.source"
:page="pdfState.currentPage"
:style="pdfState.scale"
:rotate="pdfState.rotate"
/>
<div class="pdf-style__operate">
<el-button size="small" :disabled="pdfState.currentPage === 1" @click="prePage()">上一页</el-button>
<el-button size="small" :disabled="pdfState.currentPage === pdfState.totalPages" @click="nextPage()">
下一页
</el-button>
<el-button size="small" disabled>{{ `${pdfState.currentPage} / ${pdfState.totalPages}` }}</el-button>
</div>
</div>
<script lang="ts" setup>
import VuePdfEmbed from 'vue-pdf-embed';
import { createLoadingTask } from 'vue3-pdfjs';
/**
* pdf-state
*/
const pdfState = reactive({
// 预览 pdf 文件地址
source: 'http://......',
// 当前页面
currentPage: 1,
// 总页数
totalPages: 1,
// 缩放比例
scale: 1,
// 旋转角度
rotate: 0,
// ......
});
/**
* pdf 预览
*/
function pdfPreview() {
// 获取总页数
const loadingTask = createLoadingTask(pdfState.source);
loadingTask.promise
.then((pdf: { numPages: number }) => {
pdfState.totalPages = pdf.numPages;
})
.catch(err => {
console.error(err);
});
}
/**
* pdf 上一页
*/
function prePage() {
let page = pdfState.currentPage;
page = page > 1 ? page - 1 : page;
pdfState.currentPage = page;
}
/**
* pdf 下一页
*/
function nextPage() {
let page = pdfState.currentPage;
page = page < pdfState.totalPages ? page + 1 : pdfState.totalPages;
pdfState.currentPage = page;
}
</script>
<style lang='scss' scoped>
.pdf-style {
position: relative;
padding: 30px;
background-color: #808080;
&__operate {
position: sticky;
bottom: 0;
padding: 15px;
text-align: center;
}
}
</style>
二、Word
<div ref="wordRef"></div>
import axios from 'axios';
import { renderAsync } from 'docx-preview';
import { ElMessage } from 'element-plus';
/**
* word-ref
*/
const wordRef = ref<HTMLElement>();
/**
* word 预览
*/
function wordPreview() {
axios({
method: 'GET',
responseType: 'blob',
url: 'http://......',
}).then(res => {
if (!res.data) {
ElMessage.error('文件读取失败!');
return;
}
renderAsync(res.data, wordRef.value as unknown as HTMLElement, undefined, {
// 默认和文档样式类的类名/前缀
className: 'docx',
// 启用围绕文档内容渲染包装器
inWrapper: true,
// 禁止页面渲染宽度
ignoreWidth: false,
// 禁止页面渲染高度
ignoreHeight: false,
// 禁止字体渲染
ignoreFonts: false,
// 在分页符上启用分页
breakPages: true,
// 禁用 lastRenderedPageBreak 元素的分页
ignoreLastRenderedPageBreak: true,
// 启用实验性功能(制表符停止计算)
experimental: false,
// 如果为真,xml 声明将在解析之前从xml文档中删除
trimXmlDeclaration: true,
// 启用额外的日志记录
debug: true,
// ......
});
});
}
三、Excel
<div id="luckysheetId" class="luckysheet"></div>
import { transformExcelToLuckyByUrl } from 'luckyexcel';
/**
* excel 预览
*/
function excelPreview() {
transformExcelToLuckyByUrl(props.url, '', (exportJson: any) => {
if (exportJson.sheets == null || exportJson.sheets.length == 0) {
ElMessage.error('文件读取失败!');
return;
}
// 销毁原来的表格
window.luckysheet.destroy();
// 重新创建新表格
window.luckysheet.create({
// 设定 DOM 容器的 ID
container: 'luckysheetId',
// 表格内容
data: exportJson.sheets,
// 表格标题
title: exportJson.info.name,
// 语言
lang: 'zh',
// 是否显示工具栏
showtoolbar: false,
// 是否显示公式栏
sheetFormulaBar: false,
// 是否显示顶部信息栏
showinfobar: false,
// 是否显示底部计数栏
showstatisticBar: false,
// 是否允许前台编辑
allowEdit: false,
// 是否允许复制
allowCopy: false,
// 是否允许增加行
enableAddRow: false,
// 是否允许增加列
enableAddCol: false,
// ......
});
});
}
<style lang='scss' scoped>
.luckysheet {
width: 100%;
height: 100%;
}
</style>
以上就是常用文件类型的预览,可以根据自己的需求封装在组件中从而实现多类型的预览。