先上效果图
插件安装
先说 word 文件是docx-preview插件
excel文件是用 xlsx 插件
介绍后端返回的数据
因为在拦截器处 做了对数据的处理 最后你调接口拿到的数据是 一个对象 里面包含:
url : blob对象转换的用于访问Blob
数据的临时链接。这个链接可以被用于在网页中展示二进制数据,比如显示图像或者播放音视频文件
blobs: 返回的Blob
对象,代表了从网络请求中获取到的二进制数据
这上下俩部分很重要!!!!!!!!
如果返回的普通格式的话就大家直接转化
-
const blob = new Blob([res], { type: 'application/pdf' }) //你需要的类型 转化为blob对象
-
const url = window.URL.createObjectURL(blob) //将对象转化为链接
也就是你后面掉接口返回的数据
给大家打印一下 我当时在网上搜索这类资料的时候 就是在这一部分弄糊涂了 对数据格式不了解
然后就到正式书写了
下载引入插件 (我这是v3 引入 vue2版本 csdn官网上搜vue预览文件 一大堆 大家自己搜一下)
//word文档注释
import { renderAsync } from 'docx-preview';
//excel注释
import * as XLSX from "xlsx";
Word预览
不清楚result 返回内容的往上滑 这里传递的是blob对象!!
<!-- 若是word文档格式数据号展示 我这里是加自己定义的类型判断了 fileType 大家可删除掉 -->
<div ref="refWord" id="fileShow" v-else-if="fileType == 'docx'" style="width: 100%;height: 100%;"></div>
//js代码处
const previewContainer = document.getElementById('fileShow');
renderAsync(result.blob, previewContainer) //渲染
Excel预览
不清楚result 返回内容的往上滑 这里传递的是blob对象!! 中间内容是在拿到数据渲染的时候插件数据处理 最后将处理的数据当参数传递到处理样式的方法中
<!-- 若是excel格式数据展示 -->
<div id="fileShowTwo" style="width: 100%;height: 100%;" v-else-if="fileType == 'xlsx'">
<div class="tab">
<el-radio-group size="small" v-model="excel.sheetNameActive" @change="getSheetNameTable">
<el-radio-button v-for="(item, index) in excel.sheetNames" :key="index" :label="item"></el-radio-button>
</el-radio-group>
</div>
<div
style="margin-top: 5px;border: 1px solid #a0a0a0;overflow:auto;">
<div v-html="excel.SheetActiveTable" style="padding: 10px 15px"></div>
</div>
</div>
<div v-else-if="fileType == 'mp4'" style="width: 100%;height: 100%;">
<video :src="fileAddress" controls style="width: 100%;height: 100%;"></video>
</div>
//js代码处
//表格预览所需数据 定义
const data = reactive({
excel: {
// 数据
workbook: {},
// 表名称集合
sheetNames: [],
// 激活项
sheetNameActive: "",
// 当前激活表格
SheetActiveTable: ""
}
})
const { excel } = toRefs(data);
// 视频预览所需数据
const emptyTips = ref('暂无内容');
//格式为excel时 方法中书写的内容
const reader = new FileReader(); //创建了一个FileReader对象,这个对象用于异步读取文件内容
//通过readAsArrayBuffer将blob转换为ArrayBuffer对象
reader.readAsArrayBuffer(result.blob) // 这里的res.data是blob文件流
reader.onload = (event) => {
// 读取ArrayBuffer数据变成Uint8Array
var data = new Uint8Array(event.target.result);
// 这里的data里面的类型和后面的type类型要对应
var workbook = XLSX.read(data, { type: "array" });
const sheetNames = workbook.SheetNames // 工作表名称集合
excel.value.workbook = workbook
excel.value.sheetNames = sheetNames
excel.value.sheetNameActive = sheetNames[0]
//方法
getSheetNameTable(sheetNames[0])
};
//定义的方法
const getSheetNameTable = (sheetName) => {
try {
// 获取当前工作表的数据
const worksheet = excel.value.workbook.Sheets[sheetName]
// 转换为数据 1.json数据有些问题,2.如果是html那么样式需修改
let htmlData = XLSX.utils.sheet_to_html(worksheet, { header: '', footer: '' })
htmlData = htmlData === '' ? htmlData : htmlData.replace(/<table/, '<table class="default-table" border="1px solid #ccc" cellpadding="0" cellspacing="0"')
// 第一行进行改颜色
htmlData = htmlData === '' ? htmlData : htmlData.replace(/<tr/, '<tr style="background:#b4c9e8"')
excel.value.SheetActiveTable = htmlData
} catch (e) {
// 如果工作表没有数据则到这里来处理
excel.value.SheetActiveTable = '<h4 style="text-align: center">' + emptyTips.value + '</h4>'
}
}
pdf 预览
这个需要用到iframe标签 他的blob对象的type需要是"type": "application/pdf" 大家可以看一下自己的blob对象 如果是后端返回的直接是blob格式 但是type不对 那等下我下面代码有转化 如果返回的普通数据 大家自己根据上面的格式自己转化blob对象的时候自己设置一下type
<!-- 若是pdf数据展示 -->
<iframe :src="fileAddress" type="application/pdf" v-else-if="fileType == 'pdf'" id="pdfShow" width="100%" height="100%"></iframe>
//js代码处
//格式为pdf时
const reader = new FileReader();
reader.readAsArrayBuffer(result.blob);
reader.onload = function () {
fileAddress.value = URL.createObjectURL(new Blob([reader.result], { "type": "application/pdf" }))
}
最后是jpg png ,mp4格式预览
//这里就用到blob对象转化的链接了 注意区分!!
if (type == 'jpg' || type == 'png' || type == 'mp4') {
fileAddress.value = result.url
}
//图片类型展示
<img style="width: 150px;height: 150px;" :src="fileAddress" alt="" v-if="fileType == 'jpg' || fileType == 'png'">
//视频类型展示
<div v-else-if="fileType == 'mp4'" style="width: 100%;height: 100%;">
<video :src="fileAddress" controls style="width: 100%;height: 100%;"></video>
</div>
下载文件 !!
<el-button @click="DownloadFn()"> 下载</el-button>
// 文件下载
const DownloadFn = () => {
let a = document.createElement('a')
// 下载链接
a.href = blobUploadValue.value //这个就是那个blob链接!!
// 下载文件名,如果后端没有返回,可以自己写a.download = '文件.pdf'
//这里是你上传的文件名 加上他的类型 jpg,png,docx.....
a.download = fileNameValue.value + '.' + fileType.value
document.body.appendChild(a)
// 点击a标签,进行下载
a.click()
// 移除元素
document.body.removeChild(a)
}
最后是完整代码
<el-dialog v-model="dialogTabsVisible" title="附件展示" class="file-show-box" @close="closeDialog()">
<div class="file-body">
<!-- 左侧附件列表 -->
<div class="file-left" >
<div class="list" :class="{'list-active' : listAct == index}" v-for="(item, index) in fileList" :key="index" @click="handleClick(item,index)">{{ item.name }}</div>
</div>
<div class="file-right">
<div class="downFile" v-if="fileType != 'pdf'">
<el-button @click="DownloadFn()"> 下载</el-button>
</div>
<!-- 若是图片数据展示 -->
<img style="width: 150px;height: 150px;" :src="fileAddress" alt="" v-if="fileType == 'jpg' || fileType == 'png'">
<!-- 若是txt格式数据展示 -->
<iframe :src="fileAddress" frameborder="0" v-else-if="fileType == 'txt'" style="width: 90%; height: 100%;"></iframe>
<!-- 若是pdf数据展示 -->
<iframe :src="fileAddress" type="application/pdf" v-else-if="fileType == 'pdf'" id="pdfShow" width="100%" height="100%"></iframe>
<!-- 若是word文档格式数据号展示 -->
<div ref="refWord" id="fileShow" v-else-if="fileType == 'docx'" style="width: 100%;height: 100%;"></div>
<!-- 若是excel格式数据展示 -->
<div id="fileShowTwo" style="width: 100%;height: 100%;" v-else-if="fileType == 'xlsx'">
<div class="tab">
<el-radio-group size="small" v-model="excel.sheetNameActive" @change="getSheetNameTable">
<el-radio-button v-for="(item, index) in excel.sheetNames" :key="index" :label="item"></el-radio-button>
</el-radio-group>
</div>
<div
style="margin-top: 5px;border: 1px solid #a0a0a0;overflow:auto;">
<div v-html="excel.SheetActiveTable" style="padding: 10px 15px"></div>
</div>
</div>
<div v-else-if="fileType == 'mp4'" style="width: 100%;height: 100%;">
<video :src="fileAddress" controls style="width: 100%;height: 100%;"></video>
</div>
<div v-else>
该文件暂不支持预览,请下载查看
</div>
</div>
</div>
</el-dialog>
//js部分
//表格预览所需数据
const data = reactive({
excel: {
// 数据
workbook: {},
// 表名称集合
sheetNames: [],
// 激活项
sheetNameActive: "",
// 当前激活表格
SheetActiveTable: ""
}
})
const { excel } = toRefs(data);
// 视频预览所需数据
const emptyTips = ref('暂无内容');
// 下载文件
// 文件地址
const fileAddress = ref('')
// 下载流数据
const blobUploadValue = ref('')
//我这里的参数type是其他地方传递过来的 注意甄别
const downloadFn = (id, type) => {
let params = { fileId: id }
download(params).then(result => {
console.log(result.url, 'resolve');
console.log(result.blob, 'blob');
blobUploadValue.value = result.url
if (type == 'jpg' || type == 'png' || type == 'mp4') {
//格式为图片 视频时
fileAddress.value = result.url
} else if (type == 'docx') {
//格式为word时
const previewContainer = document.getElementById('fileShow');
renderAsync(result.blob, previewContainer) //渲染
} else if (type == 'xlsx') {
//格式为excel时
const reader = new FileReader();
//通过readAsArrayBuffer将blob转换为ArrayBuffer对象
reader.readAsArrayBuffer(result.blob) // 这里的res.data是blob文件流
reader.onload = (event) => {
// 读取ArrayBuffer数据变成Uint8Array
var data = new Uint8Array(event.target.result);
// 这里的data里面的类型和后面的type类型要对应
var workbook = XLSX.read(data, { type: "array" });
const sheetNames = workbook.SheetNames // 工作表名称集合
excel.value.workbook = workbook
excel.value.sheetNames = sheetNames
excel.value.sheetNameActive = sheetNames[0]
getSheetNameTable(sheetNames[0])
};
} else if (type == 'pdf') {
//格式为pdf时
const reader = new FileReader();
reader.readAsArrayBuffer(result.blob);
reader.onload = function () {
fileAddress.value = URL.createObjectURL(new Blob([reader.result], { "type": "application/pdf" }))
}
}
})
}
// 文件下载
const DownloadFn = () => {
let a = document.createElement('a')
// 下载链接
a.href = blobUploadValue.value
// 下载文件名,如果后端没有返回,可以自己写a.download = '文件.pdf'
a.download = fileNameValue.value + '.' + fileType.value
document.body.appendChild(a)
// 点击a标签,进行下载
a.click()
// 移除元素
document.body.removeChild(a)
}
const getSheetNameTable = (sheetName) => {
try {
// 获取当前工作表的数据
const worksheet = excel.value.workbook.Sheets[sheetName]
// 转换为数据 1.json数据有些问题,2.如果是html那么样式需修改
let htmlData = XLSX.utils.sheet_to_html(worksheet, { header: '', footer: '' })
htmlData = htmlData === '' ? htmlData : htmlData.replace(/<table/, '<table class="default-table" border="1px solid #ccc" cellpadding="0" cellspacing="0"')
// 第一行进行改颜色
htmlData = htmlData === '' ? htmlData : htmlData.replace(/<tr/, '<tr style="background:#b4c9e8"')
excel.value.SheetActiveTable = htmlData
} catch (e) {
// 如果工作表没有数据则到这里来处理
excel.value.SheetActiveTable = '<h4 style="text-align: center">' + emptyTips.value + '</h4>'
}
}
这里是后端返回回来一个附件名称列表 我渲染到左侧的附件列表中 然后通过选中不同的附件 右侧展示不同的文件预览 他的文件类型我也是从这里得到的 然后我通过点击不同的附件列表 执行上面的预览方法 获取到不同的blob数据 然后进行展示
我只能给大家说一下我的逻辑 毕竟每个人代码不一样 不一定能直接复制 还是希望能帮到大家
最后贴上效果图