TXT, PDF utilizan directamente el propio navegador para obtener una vista previa
Excel usa el complemento xlsx. Este complemento necesita usar el formato de flujo de arraybuffer. Utilizo la conversión de front-end para consultar el código js para obtener más detalles. También se puede llamar fondo para devolver el flujo de datos de búfer de matriz
Word utiliza el complemento docx-preview
No digas mucho, solo sirve la comida directamente y ajusta el estilo CSS tú mismo.
1. Instale el complemento
npm instala xlsx --guardar
npm instala docx-preview --save
Dos, la parte HTML
<el-dialog
title="文件预览"
:visible.sync="dialogVisible"
fullscreen
append-to-body
:before-close="handleClose"
class="file-dialog">
<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: 500px;"></iframe>
<video v-if="videoUrl" :src="videoUrl" controls style="width: 100%;height: 100%;max-height: 800px;"></video>
<div v-if="docFile">
<div ref="file"></div>
</div>
<div v-if="xlsFile" class="excel-view-container">
<!-- Excel使用tab选项卡来模拟表格里的sheet业 -->
<el-tabs type="border-card" v-if="sheetNames && sheetNames.length" @tab-click="handleClick">
<el-tab-pane :label="item" v-for="(item, index) in sheetNames" :key="index">
<div class="excelView" v-html="excelView"></div>
</el-tab-pane>
</el-tabs>
</div>
</div>
</el-dialog>
Tres, parte js
<script>
// 定义blob对应的type
const fileTypeMap = {
"xls": "application/vnd.ms-excel",
"xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"doc": "application/msword",
"docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"pdf": "application/pdf",
"ppt": "application/pdf",
"pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
"png": "image/png",
"gif": "image/gif",
"jpeg": "image/jpeg",
"jpg": "image/jpeg",
"txt": "text/plain",
}
export default {
data() {
return {
imgUrl: '', //图片路径
pdfUrl: '', //pdf路径
videoUrl: '', //视频路径
excelView: '', //表格转换后的html数据
docFile: false, //是否是word文件
xlsFile: false, //是否是Excel文件
execlArraybufferData: null, //Excelblob转换为arraybuff数据
sheetNames: null, //从数据中获取到的sheet页数组
imgType: ['bmp', 'jpg', 'jpeg', 'png', 'tif', 'gif', 'pcx', 'tga', 'exif', 'fpx', 'svg', 'psd', 'cdr', 'pcd', 'dxf', 'ufo', 'eps', 'ai', 'raw', 'WMF', 'webp', 'avif', 'apng'],
videoType: ['wmv', 'asf', 'asx', 'rm', 'rmvb', 'mp4', '3gp', 'mov', 'm4v', 'avi', 'dat', 'mkv', 'flv', 'vob'],
wordType: ['text', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'rar', 'zip', '7z', 'apz', 'ar', 'bz', 'car', 'dar', 'cpgz', 'f', 'ha', 'hbc', 'hbc2', 'hbe','hpk','hyp'],
}
},
methods: {
// 获取文件后缀
getFileType(name) {
if (name) {
if (name.lastIndexOf(".") > -1) {
return name.slice(name.lastIndexOf(".")+1);
} else {
return false
}
}
},
// 预览文件
filePreviewPDF(path, name) {
let fileType = this.getFileType(path), url, data
// 后台接口方法url:接口地址,data给后台传的参数
this.fileView(url, data).then(res => {
let type = ''
if (fileType) {
type = fileTypeMap[fileType]
if (this.imgType.includes(fileType)) {
// 图片类型的
const blob = new Blob([res], { type })
this.imgUrl = window.URL.createObjectURL(blob)
} else if (this.videoType.includes(fileType)) {
// 视频类型的
const blob = new Blob([res])
this.videoUrl = window.URL.createObjectURL(blob)
} else if (fileType === 'pdf' || fileType === 'txt') {
// pdf和文本类型的,用iframe打开
const blob = new Blob([res], { type })
this.pdfUrl = window.URL.createObjectURL(blob)
} else if (fileType === 'doc' || fileType === 'docx') {
// word类型的用docx-preview插件
this.docFile = true
let docx = require("docx-preview")
this.$nextTick(() => {
docx.renderAsync(res, this.$refs.file).then(x => console.log("docx: finished",x))
})
} else if (fileType === 'xls' || fileType === 'xlsx') {
// 表格类型的用xlsx插件
this.xlsFile = true
let XLSX = require("xlsx")
this.XLSX = XLSX
this.execlType = type
let blob = new Blob([res], {type: this.execlType})
let reader = new FileReader()
reader.readAsArrayBuffer(blob) // blob类型转换为ArrayBuffer类型
this.tabChange(0, reader)
} else {
this.handleClose()
this.$modal.msgError('不支持此文件预览')
}
} else {
this.handleClose()
this.$modal.msgError('不支持此文件预览')
}
})
},
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 {
// 已经有数据了的时候直接获取对应sheet里的内容
let worksheet = this.workbooks.Sheets[this.sheetNames[index]];
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>
La idea surge del siguiente enlace;