新建 previewFile.vue
<template>
<div class="">
<div
v-if="['doc', 'docx', 'xls', 'xlsx'].includes(fileType)"
class="button_download"
>
<el-button type="text" @click="handleDownload">下载</el-button>
</div>
<div style="width: 100%; height: 100%">
<img
v-if="imgUrl"
:src="imgUrl"
alt=""
style="width: 100%; height: 100%"
/>
<!-- pdf和txt使用iframe -->
<iframe
v-if="pdfUrl"
:src="pdfUrl"
frameborder="0"
style="width: 100%; height: 100%; min-height: 100vh"
></iframe>
<video
v-if="videoUrl"
:src="videoUrl"
controls
style="width: 100%; height: 100%; max-height: 800px"
></video>
<div v-show="docFile">
<div ref="file"></div>
</div>
<div v-if="xlsFile" class="excel-view-container">
<!-- Excel使用tab选项卡来模拟表格里的sheet业 -->
<el-tabs
v-if="sheetNames && sheetNames.length"
type="border-card"
@tab-click="handleClick"
>
<el-tab-pane
v-for="(item, index) in sheetNames"
:key="index"
:label="item"
>
<div id="excelView" v-html="excelView"></div>
</el-tab-pane>
</el-tabs>
</div>
</div>
</div>
</template>
<script>
import * as docx from "docx-preview";
import XLSX from "xlsx";
export default {
props: ["previewType", "previewUrl"],
data() {
return {
fileType: "", //文件类型
data: "", //文件路径,blob 类型
imgUrl: "", //图片路径
pdfUrl: "", //pdf路径
videoUrl: "", //视频路径
excelView: "", //表格转换后的html数据
docFile: false, //是否是word文件
xlsFile: false, //是否是Excel文件
execlArraybufferData: null, //Excelblob转换为arraybuff数据
sheetNames: null, //从数据中获取到的sheet页数组
workbooks: null,
};
},
watch: {
previewType: {
handler(value) {
this.fileType = value;
},
immediate: true, // 重点
deep: true, // 重点
},
previewUrl: {
handler(value) {
this.data = value;
this.sheetNames = null
this.workbooks = null
this.filePreviewPDF();
},
immediate: true, // 重点
deep: true, // 重点
},
},
methods: {
handleDownload() {
this.$emit("handleDownload");
},
// 预览文件
filePreviewPDF() {
this.pdfUrl = "";
this.docFile = false;
this.xlsFile = false;
if (this.fileType == "pdf" || this.fileType == "txt") {
// pdf和文本类型的,用iframe打开
this.pdfUrl = window.URL.createObjectURL(this.data);
} else if (this.fileType == "doc" || this.fileType == "docx") {
// word类型的用docx-preview插件
this.docFile = true;
this.$nextTick(() => {
docx
.renderAsync(this.data, this.$refs.file)
.then((x) => console.log("docx: finished", x));
});
} else if (this.fileType == "xls" || this.fileType == "xlsx") {
// 表格类型的用xlsx插件
this.xlsFile = true;
this.XLSX = XLSX;
// this.execlType = type;
let reader = new FileReader();
reader.readAsArrayBuffer(this.data); // blob类型转换为ArrayBuffer类型
this.tabChange(0, reader);
} else {
this.handleClose();
this.$message.error("不支持此文件预览");
}
},
handleClick(data) {
this.tabChange(data.index);
},
tabChange(index, reader) {
this.excelView = "";
let XLSX = this.XLSX;
let _this = this;
if (!this.sheetNames) {
// 文件转换加载完成后
reader.onload = function () {
let arraybufferData = this.result;
this.execlArraybufferData = arraybufferData;
let data = new Uint8Array(arraybufferData); // es2017的方法
let workbook = XLSX.read(data, { type: "array" }); // 得到表格的array数据
_this.workbooks = workbook; // 赋值到此组件最外面,一会要用
let sheetNames = workbook.SheetNames; // 得到execl工作表名称集合,结果类似这样['sheet1','sheet2']
_this.sheetNames = sheetNames; // 赋值到此组件最外面,一会要用
let worksheet = workbook.Sheets[sheetNames[index]]; // 获取第几个工作表0就是'sheet1',以此类推
_this["excelView"] = XLSX.utils.sheet_to_html(worksheet); // 把表格的array数据转换成html数据
_this.$nextTick(function () {
// DOM加载完毕后执行,解决HTMLConnection有内容但是length为0问题。
_this.setStyle4ExcelHtml();
});
};
} else {
let worksheet = this.workbooks.Sheets[this.sheetNames[index]]; // 获取第几个工作表0就是'sheet1',以此类推
this["excelView"] = XLSX.utils.sheet_to_html(worksheet);
}
},
// 设置Excel转成HTML后的样式
setStyle4ExcelHtml() {
const excelViewDOM = document.getElementById("excelView");
if (excelViewDOM) {
const excelViewTDNodes = excelViewDOM.getElementsByTagName("td"); // 获取的是HTMLConnection
if (excelViewTDNodes) {
const excelViewTDArr = Array.prototype.slice.call(excelViewTDNodes);
for (const i in excelViewTDArr) {
const id = excelViewTDArr[i].id; // 默认生成的id格式为sjs-A1、sjs-A2......
if (id) {
const idNum = id.replace(/[^0-9]/gi, ""); // 提取id中的数字,即行号
if (idNum && (idNum === "1" || idNum === 1)) {
// 第一行标题行
excelViewTDArr[i].classList.add("class4Title");
}
if (idNum && (idNum === "2" || idNum === 2)) {
// 第二行表头行
excelViewTDArr[i].classList.add("class4TableTh");
}
}
}
}
}
},
handleClose() {
this.$emit("closeDialog", false);
},
},
};
</script>
<style lang="scss">
.button_download {
display: flex;
width: 100%;
justify-content: flex-end;
}
#excelView {
table {
color: #000;
width: 100%;
border-collapse: collapse;
border: solid 1px;
tr,
td,
th {
border: solid 1px;
text-align: center;
padding: 10px;
}
}
}
</style>
组件里面使用
<el-dialog
title="预览附件"
:visible.sync="previewAnnex"
:fullscreen="true"
:close-on-click-modal="false"
:close-on-press-escape="false"
:destroy-on-close="true"
>
<previewFile
:preview-url="previewUrl"
:preview-type="previewType"
@handleDownload="handleDownload"
/>
<div slot="footer" class="batch-dialog-footer">
<el-button type="primary" @click="previewAnnex = false">关闭</el-button>
</div>
</el-dialog>
data() {
return {
// 文件预览
previewAnnex: false,
previewUrl: '',
previewType: '',
filename: '',
};
},
methods:{
lookPdf(base){
getImageOfMinio(base).then((res) => {
if (res.data.code === 1) return this.$message.error(res.data.msg)
let wj = encodeURIComponent(res.data.data)
wj = decodeURIComponent(wj)
var myBlob = this.dataURLtoBlob(wj)
this.previewUrl = myBlob
this.previewType = this.iconByType(res.config.url)
this.filename = res.config.url
this.previewAnnex = true
})
},
// 获取文件后缀名
iconByType(filename) {
return filename.substring(filename.lastIndexOf('.') + 1, filename.length)
},
handleDownload() {
//生成地址
var myUrl = URL.createObjectURL(this.previewUrl)
//下载文件
this.downloadFile(myUrl, this.filename)
},
dataURLtoBlob(dataurl) {
let arr = dataurl.split(',')
let mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new Blob([u8arr], { type: mime })
},
downloadFile(url, name) {
let a = document.createElement('a')
a.setAttribute('href', url)
a.setAttribute('download', name)
a.setAttribute('target', '_blank')
let clickEvent = document.createEvent('MouseEvents')
clickEvent.initEvent('click', true, true)
a.dispatchEvent(clickEvent)
},
}