vue预览和下载 pdf、ppt、word、excel文档,文件类型为链接或者base64格式或者文件流,
**
方法1:word、xls、ppt、pdf 这些文件, 如果预览的文件是链接可以直接打开,可用微软官方的预览地址
**
<iframe width="100%" :src="textVisibleURl " id="myFramePPT" style="border: none;background: #f3f5f8"
title="预览" height="100%"></iframe>
data(){
return {
textVisibleURl :''
}
}
//可用window.open新开页面 或者 iframe 嵌入
//src是你文件的链接,需要可以公网访问,内网不可用,如http://********.docx
this.textVisibleURl = `https://view.officeapps.live.com/op/embed.aspx?src=${src}`; //去掉头部一些不必要的按钮操作
window.open(this.textVisibleURl)
方法2:word、xls、ppt、pdf 这些文件, 如果预览的文件是类型是文件流或者base64格式
本次我的项目中后端返回的是base64格式,在预览中需要将base64格式转为文件流
methods:{
getCustomerPoolList() {
this.$api.getCustomerPoolList({ cityName: this.cityName.toString(), homeId: this.homeInterViewSelected.map(item => item.homeId).toString() }).then(res => {
res.data.forEach(item => {
//此处两个遍历和预览无关,为业务逻辑,主要区分出文档和图片
item.mapImageObj = item.fileList.filter(file => {
return file.fileType == '.png' || file.fileType == '.jpg' || file.fileType == '.jpeg'
})[0] || {}
item.annexFileList = item.fileList.filter(file => {
return file.fileType !== '.png' && file.fileType !== '.jpg' && file.fileType !== '.jpeg'
}) || {}
//item.annexFileList为所有文档的数组
item.annexFileList.forEach((i, index) => {
//fileByte为base64格式,如上图,如果你的文件格式直接为文件流,此处 base64Str 到 byteArray 可跳过
let base64Str = i.fileByte;
const byteCharacters = atob(base64Str);
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
//针对不同的文件添加不同的BlobType,此处转为文件流URL,文件为文件流可直接从此处开始
//fileType 可以从fileName中截取,也可让后端返回
if (i.fileType == '.pdf') {
const blob = new Blob([byteArray], { type: 'application/pdf' });
i.dialogImageUrl = URL.createObjectURL(blob);
} else if (i.fileType == '.docx') {
const blob = new Blob([byteArray], { type: 'application/msword' });
i.dialogImageUrl = URL.createObjectURL(blob);
} else if (i.fileType == '.ppt' || i.fileType == '.pptx') {
const blob = new Blob([byteArray], { type: 'application/vnd.openxmlformats-officedocument.presentationml.presentation' });
i.dialogImageUrl = URL.createObjectURL(blob);
} else {
//此处为excel文件,格式为".xlsx"
const blob = new Blob([byteArray], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
i.dialogImageUrl = URL.createObjectURL(blob);
return
}
})
})
this.customerPoolObj = JSON.parse(JSON.stringify(res.data))
})
},
}
处理完后的数据,dialogImageUrl 为对象URL,预览全靠这个URL!!!
开始页面渲染
文件列表展示
预览所需的插件
#docx文档预览组件方法1
npm install @vue-office/docx vue-demi
#docx文档预览组件方法2,本文没有使用此插件预览docx
npm install mammoth
#excel文档预览组件
npm install @vue-office/excel vue-demi
#pdf文档预览组件 ,本文中没有使用此插件预览PDF
npm install @vue-office/pdf vue-demi
将两个文件复制到public目录下
ppt iframe的index.html代码,可适配移动端,pc端可删除适配移动端代码
下面的fileUrl:就是 上面处理完后的 dialogImageUrl
图片中的代码如下
let currentUrl = window.location.href;
function getUrlParams(url) {
const paramsRegex = /[?&]+([^=&]+)=([^&]*)/gi;
const params = {};
let match;
while ((match = paramsRegex.exec(url))) {
params[match[1]] = match[2];
}
return params;
}
let fileUrl = getUrlParams(currentUrl).fileUrl;
console.log("fileUrl-->", fileUrl);
//fileUrl:就是dialogImageUrl
// #pptx div的id
$("#pptx").pptxToHtml({
pptxFileUrl: fileUrl,
pptxFileName: "fileName",
slidesScale: "100%",
slideMode: false,
keyBoardShortCut: false,
});
// 适配移动端!!
let timer = setInterval(() => {
const $slides = $(".slides");
if ($slides.children().length) {
const slidesWidth = Math.max(
...Array.from($slides.children()).map((s) => s.offsetWidth)
);
const $wrapper = $("#pptx");
const wrapperWidth = window.innerWidth;
const wrapperHeight = window.innerHeight - 55;
$wrapper.css({
transform: `scale(${wrapperWidth / slidesWidth})`,
"transform-origin": "top left",
height: wrapperHeight * (1 / (wrapperWidth / slidesWidth)) + "px",
});
clearInterval(timer);
}
}, 100);
ppt/index.html中获取vue页面传进来的src链接获取到
<div class="pdfBox1" v-show="fileObj.show">
<div class="_head">
<h5>{{ fileObj.fileName }}</h5>
<i @click="closeLook" class="el-icon-arrow-left"></i>
</div>
<div class="word-wrap">
<!-- 预览pdf -->
<iframe :src="'./pdf/web/viewer.html?file=' + fileObj.url" height="100%" width="100%" id="iframe" title="预览"
v-show="fileObj.type === '.pdf'" />
<!-- 预览excel -->
<vue-office-excel v-if="fileObj.type === '.xlsx'" :src="fileObj.url" @rendered="rendered"
style="width: 100%; height: 100%" />
<!-- 无适配图片,预览Docx -->
<VueOfficeDocx :src="fileObj.url" v-if="fileObj.type === '.docx'"></VueOfficeDocx>
<!-- 预览ppt -->
<iframe width="100%" :src="pptSrc" id="myFramePPT" v-if="fileObj.type === '.pptx' || fileObj.type === '.ppt'"
style="border: none;background: #f3f5f8" title="预览" height="100%"></iframe>
</div>
</div>
文件列表的点击事件调用toFileBlob
<script>
import VueOfficePdf from "@vue-office/pdf";
import VueOfficeDocx from '@vue-office/docx'
import VueOfficeExcel from "@vue-office/excel";
import "@vue-office/docx/lib/index.css";
import "@vue-office/excel/lib/index.css";
export default {
//val为文件列表的对象,主要参数为
data(){
return{
fileObj: {
dialogImageUrl:'',
fileByte:'',
fileName:'',
fileType:'',
url :'',
},
pptSrc :''
}
}
toFileBlob(val) {
console.log('aaa', val)
this.fileObj.show = true;
this.fileObj.fileName = val.fileName;
this.fileObj.type = val.fileType
this.fileObj.fileByte = val.fileByte
this.fileObj.url = val.dialogImageUrl
if (val.fileType === '.ppt' || val.fileType === '.pptx') {
//传入到iframe中
this.pptSrc = `/ppt/index.html?fileUrl=${val.dialogImageUrl}`;
}else if (val.fileType === '.docx') {
//预览word的第二种方法
// let base64Str = val.fileByte;
// const byteCharacters = atob(base64Str);
// const byteNumbers = new Array(byteCharacters.length);
// for (let i = 0; i < byteCharacters.length; i++) {
// byteNumbers[i] = byteCharacters.charCodeAt(i);
// }
/* mammoth.convertToHtml({
arrayBuffer: new Uint8Array(byteNumbers)
}).then((resultObject) => {
this.$nextTick(() => {
this.wordText = resultObject.value;
});
}); */
}
}
</script>
下载base64类型和文件流文件
downloadGO(data, reportName) {
if (!data) {
return
}
let base64Str = data;
const byteCharacters = atob(base64Str);
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
//文件流省略上述步骤,直接下述开始,byteArray为文件流
let url = window.URL.createObjectURL(new Blob([byteArray]))
let link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.download = reportName //文件名
document.body.appendChild(link)
link.click()
},