最近做的项目要求实现预览word, pdf,png等文件功能,pdf以及png都很简单,轻松百度搞定,但是word预览研究了好久,所以特此记录分享。
前端实现预览word分为两种,一种是上传前预览(也就是前端使用input或者组件等选择文件后直接预览,此时还没有上传给后端,我定义为纯前端预览),一种是上传后预览(就是文档已经上传到后端,通过后端给的文件流实现预览)
一、先说第一种的实现方式:
首先下载安装docx-preview,引入
npm install xlsx docx-preview --save
import { defaultOptions, renderAsync } from "docx-preview"; var docxx = require("docx-preview");
我这里使用的是element ui 上传组件

上传附件
选择文件以后





myUpload(content){ console.log(content); const downUrl = URL.createObjectURL(content.file) const a = document.createElement('a'); this.$refs.selectFileNameBox.innerHTML = ""; this.$refs.selectFileNameBox.append(a); a.innerHTML = content.file.name; a.href = downUrl a.download = content.file.name; a.target = '_blank'; const addTypeArray = content.file.name.split("."); const addType = addTypeArray[addTypeArray.length - 1]; console.log(addType); this.uploadFileName = content.file.name; this.uploadFileObj = content.file; if (addType === "pdf") { const url = URL.createObjectURL(content.file); console.log(url); this.xzbjPreviewIframeSrc = url; this.xzbjIframeIsShow = true; this.xzbjDialogPreviewDiv = false; this.xzbjPreviewImgUrl = ""; this.xzbjDocPreviewFlag = false; this.previewBoxStyle = "height:400px;position: relative;overflow:hidden;" } else if(addType === "doc" || addType === "docx" || addType === "word"){ console.log("word文件预览") this.xzbjPreviewImgUrl = ""; this.xzbjPreviewIframeSrc = ""; this.xzbjDialogPreviewDiv = false; this.xzbjDocPreviewFlag = true; this.xzbjIframeIsShow = false; // 将file转为buffer let fr = new FileReader(); fr.readAsArrayBuffer(content.file); fr.addEventListener("loadend",(e) => { console.log("loadend---->", e) let buffer = e.target.result; this.docxRender(buffer); },false); } //".rar, .zip, .doc, .docx, .xls, .txt, .pdf, .jpg, .png, .jpeg," else if (["png", "jpg", "jpeg","bmp"].includes(addType)) { this.xzbjPreviewIframeSrc = ""; this.xzbjIframeIsShow = false; this.xzbjDocPreviewFlag = false; this.imgPreview(content.file); this.previewBoxStyle = "height:400px;position: relative;overflow:auto;" } else if (addType === "rar" || addType === "zip" || addType === "7z") { this.filePreviewInfo = "请下载附件进行查看" this.xzbjPreviewImgUrl = ""; this.xzbjPreviewIframeSrc = ""; this.xzbjDocPreviewFlag = false; this.xzbjDialogPreviewDiv = true; this.$message({ message: "该文件类型暂不支持预览", type: "warning", }); return false; }else{ this.filePreviewInfo = "该文件类型暂不支持预览" this.xzbjPreviewIframeSrc = ""; this.xzbjIframeIsShow = false; this.xzbjDialogPreviewDiv = true; this.xzbjPreviewImgUrl = ""; this.xzbjDocPreviewFlag = false; this.$message({ message: "请仅允许上传后缀为pdf、doc、docx、word、jpg、png、bmp、rar、zip、7z的附件", type: "warning", }); } }
// 渲染docx docxRender(buffer) { let bodyContainer = document.getElementById("demoDocContainer"); renderAsync( buffer, // Blob | ArrayBuffer | Uint8Array, 可以是 JSZip.loadAsync 支持的任何类型 bodyContainer, // HTMLElement 渲染文档内容的元素, null, // HTMLElement, 用于呈现文档样式、数字、字体的元素。如果为 null,则将使用 bodyContainer。 this.docxOptions // 配置 ).then(res => { console.log("res---->", res) }) },
下面是图片预览核心代码
imgPreview(file) { // 看支持不支持FileReader if (!file || !window.FileReader) return; // console.log(/^image/.test(file.type), "---/^image/.test(file.type)") if (/^image/.test(file.type)) { // 创建一个reader let reader = new FileReader(); // 将图片将转成 base64 格式 reader.readAsDataURL(file); // 读取成功后的回调 reader.onload = ({ target }) => { this.xzbjDialogPreviewDiv = false; this.xzbjPreviewImgUrl = target.result; //将img转化为二进制数据 // console.log("target:", target); }; } },
这样就实现了纯前端预览word功能
二、接下来实现 配合后端预览word
根据后端返回的流预览word

request({ method: "get", url: "/notice/noticeFileView", responseType: 'blob', params:{ id:row.id }, headers: { "Content-Type": 'application/json' }, }).then(res=>{ console.log(res,"---文件预览"); if(row.suffix.includes("pdf")){ this.previewPdfFn(res); // let blob = new Blob([res],{ // type: 'application/pdf' // }) // let url = window.URL.createObjectURL(blob); this.xqPreviewImgUrl = ""; this.xqPreviewPdfUrl = this.previewPdfFn(res); this.xqPdfPreviewFlag = true; this.xqDocPreviewFlag = false; this.xqPerviewStyle = "height:600px;position: relative;overflow:hidden" }else if(row.suffix.includes("docx") || row.suffix.includes("doc")|| row.suffix.includes("word")){ console.log("预览word") this.xqDocPreviewFlag = true; let blob = new Blob([res],{ type: 'application/pdf' }) this.$nextTick(()=>{ console.log(this.$refs.xqDocContainer,"---this.$refs.xqDocContainer") docxx.renderAsync(blob, this.$refs.xqDocContainer) }) } else if (row.suffix === ".rar" || row.suffix === ".zip" || row.suffix === "7z") { this.xqDocPreviewFlag = false; this.xzbjPreviewImgUrl = ""; this.xzbjPreviewIframeSrc = ""; this.$message({ message: "该文件类型暂不支持预览", type: "warning", }); return false; }else if([".png", ".jpg", ".jpeg",".bmp"].includes(row.suffix)){ let blob = new Blob([res],{ type: 'application/pdf' }) console.log(blob,"---blob") let url = window.URL.createObjectURL(blob); this.xqPreviewImgUrl = url; this.xqPdfPreviewFlag = false; this.xqDocPreviewFlag = false; this.xqPreviewPdfUrl = ""; this.xqPerviewStyle = "height:600px;position: relative;overflow:auto" } this.xqDialogPreviewDiv = false; }).catch(err=>{ console.log(err,"--文件预览失败") })
完毕
下面是参考链接:
https://www.jianshu.com/p/8e1e90570c52 预览word excel
https://blog.csdn.net/kaimo313/article/details/127012225 vue里使用docx-preview预览docx文件
https://volodymyrbaydalka.github.io/docxjs/
最后是一个好友赠送的组件
import { defaultOptions, renderAsync } from "docx-preview"; console.log(defaultOptions); export default { name: 'DocxPreview', data () { return { docxOptions: { className: "kaimo-docx-666", // string:默认和文档样式类的类名/前缀 inWrapper: true, // boolean:启用围绕文档内容的包装器渲染 ignoreWidth: false, // boolean:禁用页面的渲染宽度 ignoreHeight: false, // boolean:禁止渲染页面高度 ignoreFonts: false, // boolean:禁用字体渲染 breakPages: true, // boolean:在分页符上启用分页 ignoreLastRenderedPageBreak: true, // boolean:在 lastRenderedPageBreak 元素上禁用分页 experimental: false, // boolean:启用实验功能(制表符停止计算) trimXmlDeclaration: true, // boolean:如果为true,解析前会从 xml 文档中移除 xml 声明 useBase64URL: false, // boolean:如果为true,图片、字体等会转为base 64 URL,否则使用URL.createObjectURL useMathMLPolyfill: false, // boolean:包括用于 chrome、edge 等的 MathML polyfill。 showChanges: false, // boolean:启用文档更改的实验性渲染(插入/删除) debug: false, // boolean:启用额外的日志记录 } }; }, methods: { getFile(){ this.handlePreview() }, handlePreview() { let file = document.getElementById("file").files[0]; console.log(file); // 将file转为buffer let fr = new FileReader(); fr.readAsArrayBuffer(file); fr.addEventListener("loadend",(e) => { console.log("loadend---->", e) let buffer = e.target.result; this.docxRender(buffer); },false); }, // 渲染docx docxRender(buffer) { let bodyContainer = document.getElementById("bodyContainer"); renderAsync( buffer, // Blob | ArrayBuffer | Uint8Array, 可以是 JSZip.loadAsync 支持的任何类型 bodyContainer, // HTMLElement 渲染文档内容的元素, null, // HTMLElement, 用于呈现文档样式、数字、字体的元素。如果为 null,则将使用 bodyContainer。 this.docxOptions // 配置 ).then(res => { console.log("res---->", res) }) } }, };
结束啦,每天进步一点点,早日成为大神。啦啦啦