如果项目是外网,iframe + 微软提供的免费在线预览office接口 https://view.officeapps.live.com/op/view.aspx?src=http://static.shanhuxueyuan.com/test6.docx 实现以上类型文件的预览(还有doc/ppt)等
如果项目是内网,没做内网穿透,那就只能装插件
xls/xlsx/docx
用的 vue-office,安装使用看官网介绍,非常详细简洁,但是注意xls加载不了excel样式
1.xls
2.xlsx
3.docx
pdf/txt
vue-office也有pdf插件@vue-office/pdf,不过我用了iframe实现,因为浏览器自带的PDF功能挺丰富,还能加载.txt文件
pptx
使用PPTXjs实现
- 点此下载 PPTXjs压缩包,解压后放在public目录下
- 在index.html中引入css/js
css
<link rel="stylesheet" href="/PPTXjs/css/pptxjs.css">
<link rel="stylesheet" href="/PPTXjs/css/nv.d3.min.css"> <!-- for charts graphs -->
js
<script type="text/javascript" src="/PPTXjs/js/jquery-1.11.3.min.js"></script>
<script type="text/javascript" src="/PPTXjs/js/jszip.min.js"></script> <!-- v2.. , NOT v.3.. -->
<script type="text/javascript" src="/PPTXjs/js/filereader.js"></script> <!--https://github.com/meshesha/filereader.js -->
<script type="text/javascript" src="/PPTXjs/js/d3.min.js"></script> <!-- for charts graphs -->
<script type="text/javascript" src="/PPTXjs/js/nv.d3.min.js"></script> <!-- for charts graphs -->
<script type="text/javascript" src="/PPTXjs/js/pptxjs.js"></script>
<script type="text/javascript" src="/PPTXjs/js/divs2slides.js"></script> <!-- for slide show -->
- iframe获取动态文件地址
在PPTXjs/index.html页面,获取传给iframe的动态文件地址
代码
<template>
<el-dialog
v-loading="loading"
:title="dialogTitle"
fullscreen
lock-scroll
center
ref="dialog"
custom-class="dialog"
:close-on-press-escape="false"
:visible.sync="dialogVisible"
:before-close="handleClose"
>
<!-- <vue-office-pdf
v-if="['pdf'].includes(fileType)"
:src="fileUrl"
:style="{ height: bodyHeight + 'px' }"
@rendered="renderedHandler('pdf')"
@error="errorHandler('pdf')"
/> -->
<vue-office-docx
v-if="['doc', 'docx'].includes(fileType)"
:src="fileUrl"
:style="{ height: bodyHeight + 'px' }"
@rendered="renderedHandler('doc')"
@error="errorHandler('doc')"
/>
<vue-office-excel
v-else-if="['xls', 'xlsx'].includes(fileType)"
:src="fileUrl"
:options="excelOptions"
:style="{ height: bodyHeight + 'px' }"
@rendered="renderedHandler('xls')"
@error="errorHandler('xls')"
/>
<iframe
v-else-if="['pdf', 'txt', 'pptx'].includes(fileType)"
id="iframe"
:src="
['pdf', 'txt'].includes(fileType)
? fileUrl
: `/PPTXjs-master/index.html?file=` + fileUrl
"
:style="{ height: bodyHeight + 'px' }"
></iframe>
<div slot="footer">
<el-button type="primary" round @click="handleClose">关闭</el-button>
</div>
</el-dialog>
</template>
<script>
//引入VueOfficeDocx组件
import VueOfficeDocx from "@vue-office/docx";
//引入相关样式
import "@vue-office/docx/lib/index.css";
//引入VueOfficeExcel组件;
import VueOfficeExcel from "@vue-office/excel";
//引入相关样式
import "@vue-office/excel/lib/index.css";
//引入VueOfficePdf组件
// import VueOfficePdf from "@vue-office/pdf";
export default {
components: {
VueOfficeDocx,
VueOfficeExcel,
// VueOfficePdf,
},
data() {
return {
dialogVisible: false,
dialogTitle: "",
loading: false,
frontUrl: process.env.VUE_APP_BASE_API + "/file/preOrDown?filePath=",
behindtUrl: "&type=0",
// excel: "http://static.shanhuxueyuan.com/demo/excel.xlsx", //设置文档地址
// pdf: "http://static.shanhuxueyuan.com/test.pdf", //设置文档地址
// docx: "http://static.shanhuxueyuan.com/test6.docx", //设置文档网络地址,可以是相对地址
// https://www.hengdianworld.com/DownloadFile/%E6%A8%AA%E5%BA%97%E5%BD%B1%E8%A7%86%E5%9F%8E%E6%B8%B8%E8%A7%88%E6%89%8B%E5%86%8C.docx
docOptions: {
className: "docx", //class name/prefix for default and document style classes
inWrapper: true, //enables rendering of wrapper around document content
ignoreWidth: false, //disables rendering width of page
ignoreHeight: false, //disables rendering height of page
ignoreFonts: false, //disables fonts rendering
breakPages: true, //enables page breaking on page breaks
ignoreLastRenderedPageBreak: false, //disables page breaking on lastRenderedPageBreak elements
experimental: false, //enables experimental features (tab stops calculation)
trimXmlDeclaration: true, //if true, xml declaration will be removed from xml documents before parsing
useBase64URL: false, //if true, images, fonts, etc. will be converted to base 64 URL, otherwise URL.createObjectURL is used
useMathMLPolyfill: false, //includes MathML polyfills for chrome, edge, etc.
showChanges: false, //enables experimental rendering of document changes (inserions/deletions)
debug: false, //enables additional logging
},
excelOptions: {
xls: true, //预览xlsx文件设为false;预览xls文件设为true
// minColLength: 0, // excel最少渲染多少列,如果想实现xlsx文件内容有几列,就渲染几列,可以将此值设置为0.
// minRowLength: 0, // excel最少渲染多少行,如果想实现根据xlsx实际函数渲染,可以将此值设置为0.
// widthOffset: 10, //如果渲染出来的结果感觉单元格宽度不够,可以在默认渲染的列表宽度上再加 Npx宽
// heightOffset: 10, //在默认渲染的列表高度上再加 Npx高
beforeTransformData: (workbookData) => {
return workbookData;
}, //底层通过exceljs获取excel文件内容,通过该钩子函数,可以对获取的excel文件内容进行修改,比如某个单元格的数据显示不正确,可以在此自行修改每个单元格的value值。
transformData: (workbookData) => {
return workbookData;
}, //将获取到的excel数据进行处理之后且渲染到页面之前,可通过transformData对即将渲染的数据及样式进行修改,此时每个单元格的text值就是即将渲染到页面上的内容
},
fileUrl: "",
fileType: "",
bodyHeight: "",
};
},
methods: {
init(row) {
this.loading = true;
this.dialogVisible = true;
this.dialogTitle = row.originalTitle;
this.fileUrl = this.frontUrl + row.filePath + this.behindtUrl;
this.fileType = row.filePath.split(".")[1];
console.log("fileType", this.fileType);
console.log("fileUrl", this.fileUrl);
this.excelOptions.xls = this.fileType == "xls" ? true : false;
this.$nextTick(() => {
const dialog = document.getElementsByClassName("dialog")[0];
const dialogChildren = dialog.children;
const headerHeight = dialogChildren[0].offsetHeight;
const footerHeight = dialogChildren[2].offsetHeight;
this.bodyHeight = dialog.offsetHeight - headerHeight - footerHeight;
if (["pdf", "txt", "pptx"].includes(this.fileType)) {
const iframe = document.getElementById("iframe");
// attachEvent为IE专用方法
if (iframe.attachEvent) {
iframe.attachEvent("onload", function () {
console.log("iframe is now loaded.");
this.loading = false;
});
} else {
iframe.onload = () => {
console.log("iframe is now loaded.");
this.loading = false;
};
}
}
});
},
renderedHandler(type) {
console.log("渲染完成", type);
this.loading = false;
},
errorHandler(type) {
console.log("渲染失败", type);
this.loading = false;
},
handleClose() {
this.dialogVisible = false;
this.dialogTitle = "";
this.fileUrl = "";
this.fileType = "";
this.bodyHeight = "";
},
},
};
</script>
<style lang="scss" scoped>
::v-deep {
.el-dialog--center .el-dialog__body {
padding: 0;
}
}
iframe {
width: 100%;
display: block;
}
</style>
参考
https://blog.csdn.net/q2qwert/article/details/130905525
https://blog.csdn.net/KK_vicent/article/details/130827910