实现附件在线预览是一个很常用的功能,这次正好碰到这样的需求,记录一下自己实现的过程。
首先是插件的选择,网上实现预览的方法主要有两种,一个是vue-office插件,另一个是docx-preivew插件。看网上其他网友的教程都能够实现文件的在线预览。
选择一:vue-office插件
vue-office官网地址:docx文件预览 | vue-office
不知道是不是因为自己vue版本太低不兼容这个插件,还是其他原因,按照方法怎么都实现不了文件的预览。(项目的vue版本是2.5.17,如果有遇到类似情况解决了的,欢迎指教)
选择二:docx-preivew插件
参考文章:docx-preview在vue内的使用_vue docx-preview-CSDN博客
第一种方式实现不了,就选择了第二种。第二个插件主要的问题就是版本的选择。一开始直接无脑操作根据命令(npm i docx-preview)安装插件:
结果出事了。我的vue版本过低,不能直接使用最新版本的docx-preivew插件。后面终于,在网上找到类似的问题,需要安装指定版本的插件,命令:
npm i docx-preview@0.1.20
有两种实现方法 :
一、上传文件进行预览
<el-dialog
title="文件预览"
:visible="dialogVisible"
show-close
append-to-body
width="60%"
:before-close="cancelDialog"
>
<input type="file" @change="handleFileChange" />
<div class="container" ref="container" id="container"></div>
<div slot="footer" class="dialog-footer tc">
<button class="btn-submit btn-submit-sm" @click="cancelDialog()">关闭</button>
</div>
</el-dialog>
async handleFileChange(e){
const file = e.target.files[0];
const blob = await this.fileToBlob(file);
this.preview(blob,this.$refs.container,this.$refs.container);
},
fileToBlob(file) {
return new Promise((resolve,) => {
let reader = new FileReader();
reader.readAsArrayBuffer(file);
let blob = null;
reader.onload = (e) => {
if (typeof e.target.result === "object") {
blob = new Blob([e.target.result]);
} else {
blob = e.target.result;
}
resolve(blob);
};
});
},
async preview(blob,createEl,styleEl) {
await renderAsync(
blob, // could be any type that supported by JSZip.loadAsync
createEl, //element to render document content,
styleEl, //element to render document styles, numbeings, fonts. If null, bodyContainer will be used.
{
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: true, //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, //@deprecated includes MathML polyfills for chrome, edge, etc.
renderChanges: false, //enables experimental rendering of document changes (inserions/deletions)
renderHeaders: true, //enables headers rendering
renderFooters: true, //enables footers rendering
renderFootnotes: true, //enables footnotes rendering
renderEndnotes: true, //enables endnotes rendering
debug: false, //enables additional logging
},
);
},
实现效果:
二、后端提供接口下载文件后预览
<el-button
@click="toPreView($event, row)"
type="text"
class="pd-0 btn-table-wid2"
>预览
</el-button>
<el-dialog
title="文件预览"
:visible="dialogVisible"
show-close
append-to-body
width="60%"
:before-close="cancelDialog"
>
<div class="container" ref="container" id="container"></div>
<div slot="footer" class="dialog-footer tc">
<button class="btn-submit btn-submit-sm" @click="cancelDialog()">关闭</button>
</div>
</el-dialog>
created() {
this.previewFile(this.docId);
},
methods: {
previewFile() {
const inParam = {
DOC_ID: this.docId,
STAFF_NAME: this.$store.getters.staffName,
SYS_USER_CODE: this.$store.getters.systemUserCode
};
this.$preview(this.mciApi.common.file.previewFile, {
...inParam
},false).then(r => {
this.preview(r,this.$refs.container,this.$refs.container);
})
},
async preview(blob,createEl,styleEl) {
await renderAsync(
blob, // could be any type that supported by JSZip.loadAsync
createEl, //element to render document content,
styleEl, //element to render document styles, numbeings, fonts. If null, bodyContainer will be used.
{
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: true, //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, //@deprecated includes MathML polyfills for chrome, edge, etc.
renderChanges: false, //enables experimental rendering of document changes (inserions/deletions)
renderHeaders: true, //enables headers rendering
renderFooters: true, //enables footers rendering
renderFootnotes: true, //enables footnotes rendering
renderEndnotes: true, //enables endnotes rendering
debug: false, //enables additional logging
},
);
},
cancelDialog(){
this.$emit('cancelDialog');
},
}
注意:
1、this.$preview 是封装的post请求方法,需要设置 responseType: 'blob'
2、this.mciApi.common.file.previewFile 是后台提供的文件下载接口,返回文件流数据,请求成功后将文件流转换成 blob 类型,进行文件预览。
3、转blob:const blob = new Blob([content], { type: 'application/pdf' });
实现效果: