今天小编给大家分享一下vue项目怎么实现前端预览word与pdf格式文件的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。
页面上传pdf文件效果如下:
页面预览pdf文件效果如下:
页面上传word文件效果如下:
页面预览word文件效果如下:
这里先从上传组件页面说起,上传页面组件完整代码如下,按钮里面v-show=“$checkPermission([‘Register_tuotpUpload’])“都是给这个按钮设置了按钮权限的,我们只需要关注上传那一部分的代码即可,我们用了el-upload组件实现的手动上传,由于需求要求只能上传word和pdf,所以能看到属性设置的有 accept=”.pdf, .doc, .docx”,然后不展示上传成功的文件的列表设置的属性有:show-file-list=“false”,而handleExceed回调函数和limit都是为了限制只能上传一个文件,上传前的回调钩子函数beforeAvatarUpload里进行了文件类型判断与提醒,手动上传是通过UploadFile里进行完成的,需要注意的是由于docx-preview这个插件只能预览后缀为docx的word文件,如果是doc后缀格式的word文件一定要让后端强制将上传doc格式的文件改为docx格式,目前对于doc格式的word文件实现网页在线预览我只想到了docx-preview这个插件和这个解决办法:
<template> <div class="app-container"> <div class="cardWhite"> <div class="itemBox"> <div class="headerTitle">基本信息</div> <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="120px" class="demo-ruleForm" > <el-row> <el-col :span="12"> <el-form-item label="链路名称" prop="name"> <el-input v-model="ruleForm.name" placeholder="请输入链路名称" clearable ></el-input> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="链路类型" prop="linkType"> <el-select v-model="ruleForm.linkType" placeholder="请选择链路类型" clearable > <el-option v-for="item in linkTypeList" :key="item.val" :label="item.key" :value="item.val" ></el-option> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="链路走向" prop="go"> <el-row> <el-col :span="10"> <el-select v-model="ruleForm.srcNetwork" placeholder="请选择" clearable @clear="clearSrc" @change="srcChange" > <el-option v-for="item in scrList" :key="item.val" :label="item.key" :value="item.val" ></el-option> </el-select> </el-col> <el-col :span="4"> <div > <img src="@/assets/toRight.png" /> </div> </el-col> <el-col :span="10"> <el-select v-model="ruleForm.dstNetwork" placeholder="请选择" :clearable="false" @clear="clearDst" @change="dstChange" > <el-option v-for="item in dstList" :key="item.val" :label="item.key" :value="item.val" ></el-option> </el-select> </el-col> </el-row> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="物理位置" prop="physicalPosition"> <el-input v-model="ruleForm.physicalPosition" placeholder="请输入链路物理位置" clearable ></el-input> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="所属机构" prop="orangeName"> <el-input v-model="ruleForm.orangeName" placeholder="例:xx市公安局" clearable ></el-input> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="行政区编码" prop="organCode"> <el-input v-model="ruleForm.organCode" placeholder="请输入行政区编码,例:027" clearable ></el-input> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="责任人" prop="dutyPerson"> <el-input v-model="ruleForm.dutyPerson" placeholder="请输入链路责任人" clearable ></el-input> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="责任人电话" prop="dutyTel"> <el-input v-model="ruleForm.dutyTel" placeholder="请输入链路责任人电话" clearable ></el-input> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="公安网邮箱" prop="dutyEmail"> <el-input v-model="ruleForm.dutyEmail" placeholder="请输入负责人公安网邮箱" clearable ></el-input> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="链路IP地址" prop="ip"> <el-input v-model="ruleForm.ip" placeholder="请输入链路IP地址" clearable ></el-input> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="链路端口" prop="port"> <el-input-number placeholder="请输入链路端口" type="text" :min="0" :controls="false" v-model.trim="ruleForm.port" ></el-input-number> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="管理页面" prop="webUrl"> <el-input v-model="ruleForm.webUrl" placeholder="请输入链路管理页面" clearable ></el-input> </el-form-item> </el-col> </el-row> <el-row> <el-col :push="2"> <el-button class="filter-item" type="primary" icon="el-icon-plus" @click="saveForm" v-show="$checkPermission(['Register_boundarySave'])" > 保存 </el-button> </el-col> </el-row> </el-form> </div> <div class="itemBox"> <div class="headerTitle">链路拓扑图</div> <el-form :model="tuopuForm" ref="tuopuForm" label-width="120px"> <el-row> <el-col :span="12"> <el-form-item label="拓扑图" prop="fileName"> <el-input v-model="tuopuForm.fileName" placeholder="请选择电脑中拓扑图文件" clearable disabled > <el-upload accept=".pdf, .doc, .docx" action="string" :limit="1" :on-exceed="handleExceed" :before-upload="beforeAvatarUpload" :http-request="UploadFile" slot="append" :show-file-list="false" > <el-button type="primary" v-show="$checkPermission(['Register_tuotpUpload'])" icon="el-icon-upload2" >上传</el-button > </el-upload> </el-input> </el-form-item> </el-col> <el-col :span="3" :push="1"> <el-button class="filter-item" type="primary" icon="el-icon-view" @click="preview" v-show="$checkPermission(['Register_tuotpPreview'])" > 预览 </el-button> </el-col> </el-row> </el-form> </div> <div class="itemBox"> <div class="headerTitle">设备信息列表</div> <el-row type="flex" justify="end" > <el-button class="filter-item" type="primary" icon="el-icon-plus" @click="addEquipment" v-show="$checkPermission(['Register_equipmentAdd'])" > 添加 </el-button> </el-row> <div> <commonTable :tableHead="tableHead" :tableData="tableData" :dataFiter="true" :selectionFlag="false" :dropdownList="[]" :resizable="true" :tableLoading="tableLoading" :showListD="showListD" :toolBoxFlag="false" @sortChange="() => {}" @selection-change="() => {}" @selectAction="() => {}" @addData="() => {}" :actionFlag="false" :actionList="[]" :freeElfFlag="false" :xuhaoFlag="true" :freeWidth="480" > <template slot-scope="scope" slot="doSomething" fixed="right" align="left" > <el-button icon="el-icon-edit" type="primary" @click="handlerUpdate(scope.rows)" v-show="$checkPermission(['Register_equipmentEdit'])" >编辑</el-button > <el-button icon="el-icon-delete" type="danger" @click="handlerDelete(scope.rows)" v-show="$checkPermission(['Register_equipmentDelete'])" >删除</el-button > </template> </commonTable> </div> </div> <div class="itemBox"> <div class="headerTitle">链路注册</div> <el-row type="flex" justify="end" > <el-button class="filter-item" type="primary" icon="el-icon-plus" @click="addRegister" v-show="$checkPermission(['Register_registerAdd'])" > 添加 </el-button> </el-row> <div> <commonTable :tableHead="Register_tableHead" :tableData="Register_tableData" :dataFiter="true" :selectionFlag="false" :dropdownList="[]" :resizable="true" :tableLoading="Register_tableLoading" :showListD="Register_showListD" :toolBoxFlag="false" @sortChange="() => {}" @selection-change="() => {}" @selectAction="() => {}" @addData="() => {}" :actionFlag="false" :actionList="[]" :freeElfFlag="false" :xuhaoFlag="true" :freeWidth="480" > <template slot-scope="scope" slot="status"> <el-tag v-if="scope.rows.status == 1">已注册</el-tag> <el-tag type="success" v-if="scope.rows.status == 0" >未注册</el-tag > <el-tag type="danger" v-if="scope.rows.status == 2" >注册失败</el-tag > </template> <template slot-scope="scope" slot="doSomething" fixed="right" align="left" > <el-button icon="el-icon-edit" type="primary" v-if=" scope.rows.status == 1 && $checkPermission(['Register_registerOff']) " @click="handlerLogoff(scope.rows)" >注销</el-button > <el-button icon="el-icon-edit" type="primary" v-if=" ($checkPermission(['Register_registerGo']) && scope.rows.status == 0) || scope.rows.status == 2 " @click="handlerLogoff(scope.rows)" >注册</el-button > <el-button icon="el-icon-delete" type="danger" v-if="$checkPermission(['Register_registerDelete'])" @click="Register_handlerDelete(scope.rows)" >删除</el-button > </template> </commonTable> </div> </div> </div> <!-- 添加和编辑设备弹窗 --> <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible" width="800px" :before-close="handleClose" :close-on-click-modal="false" > <add-edit @refresh="fetchData" @closeDialog="dialogFormVisible = false" class="AddEdit" ref="AddEdit" :devTypeList="EquipmentList" v-if="dialogFormVisible" /> <div slot="footer" class="dialog-footer"> <el-button @click="dialogFormVisible = false"> 取消 </el-button> <el-button type="primary" @click="submitForm()"> 确定 </el-button> </div> </el-dialog> <!-- 链路注册弹窗 --> <el-dialog title="链路注册" :visible.sync="Register_dialogFormVisible" width="800px" :before-close="Register_handleClose" :close-on-click-modal="false" > <register-add @reg_refresh="Register_fetchData" @reg_closeDialog="Register_dialogFormVisible = false" ref="RegisterAdd" v-if="Register_dialogFormVisible" /> <div slot="footer" class="dialog-footer"> <el-button @click="Register_dialogFormVisible = false"> 取消 </el-button> <el-button type="primary" @click="Register_submitForm()"> 确定 </el-button> </div> </el-dialog> </div> </template> <script> import commonTable from "@/components/common-table"; import Pagination from "@/components/Pagination"; import AddEdit from "./EquipmentAddEdit.vue"; import RegisterAdd from "./RegisterAdd.vue"; import * as api from "@/api/datax-register.js"; import axios from "axios"; import { getToken } from "@/utils/auth"; export default { components: { Pagination, commonTable, AddEdit, RegisterAdd }, data() { const validateGo = (rule, value, callback) => { // if (!value) { // callback("请输入平台IP地址"); // } else { // let index = value.indexOf("/"); // let findHengT = value.indexOf("-"); // let findHengP = value.indexOf("——"); // if (index > -1 || findHengT > -1 || findHengP > -1) { // callback("请输入正确格式的平台IP地址"); // } else { // validator.IpArea(rule, value, callback); // } // } if (!this.ruleForm.srcNetwork || !this.ruleForm.dstNetwork) { callback("请选择链路走向"); } else { callback(); } }; return { ruleForm: { name: "", linkType: "", srcNetwork: "", dstNetwork: "", physicalPosition: "", orangeName: "", organCode: "", dutyPerson: "", dutyTel: "", dutyEmail: "", ip: "", port: undefined, webUrl: "" }, rules: { name: [{ required: true, message: "请输入链路名称", trigger: "blur" }], linkType: [ { required: true, message: "请选择链路类型", trigger: "blur" } ], go: [ { required: true, message: "请选择链路走向", trigger: "blur", validator: validateGo } ], physicalPosition: [ { required: false, message: "请输入链路物理位置", trigger: "blur" } ], orangeName: [ { required: true, message: "请输入所属机构", trigger: "blur" } ], organCode: [ { required: true, message: "请输入行政区编码", trigger: "blur" } ], dutyPerson: [ { required: true, message: "请输入链路责任人", trigger: "blur" } ], dutyTel: [ { required: true, message: "请输入链路责任人电话", trigger: "blur" } ], dutyEmail: [ { required: false, message: "请输入负责人公安网邮箱", trigger: "blur" } ], ip: [{ required: false, message: "请输入链路IP地址", trigger: "blur" }], port: [{ required: true, message: "请输入链路端口", trigger: "blur" }], webUrl: [ { required: false, message: "请输入链路管理页面", trigger: "blur" } ] }, linkTypeList: [], scrList: [], dstList: [], tuopuForm: { fileName: "", fileUrl: "" }, tableHead: [ { label: "设备名称", prop: "name", type: "normal", sortable: false }, { label: "设备类型", prop: "devType", type: "normal", sortable: false // width: 150 }, { label: "厂商", prop: "manufacturer", type: "normal", sortable: false // width: 150 }, { label: "型号", prop: "model", type: "normal", sortable: false // width: 150 }, { label: "设备IP", prop: "devIp", type: "normal", sortable: false }, { label: "子网掩码", prop: "ipMask", type: "normal", sortable: false // width: 150 }, { label: "网关", prop: "ipGaway", type: "normal", sortable: false // width: 150 }, { label: "安装时间", prop: "installTime", type: "normal", sortable: false, width: 180 }, { label: "操作", prop: "doSomething", type: "slot", sortable: false, slotName: "doSomething", width: 220 } // { // label: "任务详情", // prop: "log_text", // type: "slot", // sortable: false, // slotName: "log_text", // width: 100 // } ], showListD: [ "name", "devType", "manufacturer", "model", "devIp", "ipMask", "ipGaway", "installTime", "doSomething" // "log_text" ], dialogStatus: "", dialogFormVisible: false, textMap: { update: "编辑设备", Edit: "编辑设备", edit: "编辑设备", create: "添加设备" }, tableData: [], tableLoading: false, Register_tableHead: [ { label: "平台名称", prop: "name", type: "normal", sortable: false }, { label: "平台IP地址", prop: "ip", type: "normal", sortable: false }, { label: "平台端口", prop: "port", type: "normal", sortable: false }, { label: "平台唯一标识", prop: "uniquePlatformCode", type: "normal", sortable: false }, { label: "注册时间", prop: "lastTime", type: "normal", sortable: false, width: 180 }, { label: "注册状态", prop: "status", type: "slot", slotName: "status", sortable: false }, { label: "操作", prop: "doSomething", type: "slot", sortable: false, slotName: "doSomething", width: 220 } // { // label: "任务详情", // prop: "log_text", // type: "slot", // sortable: false, // slotName: "log_text", // width: 100 // } ], Register_tableData: [], Register_tableLoading: false, Register_showListD: [ "name", "ip", "port", "uniquePlatformCode", "lastTime", "status", "doSomething" // "log_text" ], Register_dialogFormVisible: false, fileList: null, //拓扑图文件列表 tuotpData: null, EquipmentList: [], originalList: [] }; }, created() { this.getNews(); }, methods: { getNews() { //获取边界信息 this.getBoundaryDetail(); //获取拓扑图 this.getTuotp(); //获取设备列表 this.fetchData(); //获取链路注册列表 this.Register_fetchData(); //获取公共下拉 this.getSelect(); }, saveForm() { this.$refs["ruleForm"].validate(valid => { if (valid) { let params = { ...this.ruleForm }; console.log("修改入参", params); //修改 api .boundaryEdit(params) .then(res => { console.log("修改", res); if (res.code == 200) { this.$notify({ title: "成功", message: "边界信息修改成功", type: "success", duration: 2000 }); } }) .catch(err => {}); } }); }, preview() { console.log("预览", this.fileList, this.tuopuForm); if (!this.fileList) { this.$message.error( "拓扑图文件为空不能预览,请先上传拓扑图文件后再预览", 6000 ); return false; } this.$router.push({ path: "TuotpPreview", query: { fileName: this.tuopuForm.fileName, fileUrl: this.tuopuForm.fileUrl } }); }, addEquipment() { this.dialogStatus = "create"; this.dialogFormVisible = true; setTimeout(() => { this.$refs["AddEdit"].dialogStatus = "create"; // this.$refs.AddEdit.resetTransferDetail(); // this.getCommonData(); }, 1); }, //获取公共下拉 getSelect() { api .getLinkEquimentSelect({ clsName: "link_direction" }) .then(res => { console.log("链路走向下拉", res); this.scrList = res.data; this.dstList = res.data; this.originalList = res.data; }) .catch(err => {}); api .getLinkEquimentSelect({ clsName: "link_type" }) .then(res => { console.log("链路类型下拉", res); this.linkTypeList = res.data; }) .catch(err => {}); api .getLinkEquimentSelect({ clsName: "dev_type" }) .then(res => { console.log("设备类型下拉", res); this.EquipmentList = res.data; }) .catch(err => {}); }, //获取边界信息 getBoundaryDetail() { api .boundaryDetail() .then(res => { // console.log("获取边界信息", res); this.ruleForm = res.data; this.ruleForm.port = res.data.port ? res.data.port : undefined; }) .catch(err => {}); }, //获取拓扑图 getTuotp() { api .boundaryTuopoDetail() .then(res => { // console.log("获取拓扑图成功", res); this.tuopuForm = res.data; this.tuopuPreview(); }) .catch(err => { // console.log("获取拓扑图失败", err); }); }, //获取设备列表 fetchData() { this.tableLoading = true; api .equipmentList({ page: 1, page_size: 99999, ip: "" }) .then(res => { // console.log("设备列表", res); if (res.code == 200) { this.tableData = res.data.list; this.tableLoading = false; } }) .catch(err => {}); }, //编辑 handlerUpdate(row) { // console.log("点了修改", row); this.dialogStatus = "Edit"; this.dialogFormVisible = true; setTimeout(() => { this.$refs["AddEdit"].setData(row); this.$refs["AddEdit"].dialogStatus = "Edit"; }, 1); }, handleClose() { this.dialogFormVisible = false; }, submitForm() { this.$refs["AddEdit"].submitForm(); }, //删除 handlerDelete(row) { this.$confirm("确定删除吗?", "提示", { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" }).then(() => { api .equipmentDelete(row) .then(response => { if (response.code == 200) { this.fetchData(); this.$notify({ title: "成功", message: "删除成功", type: "success", duration: 2000 }); } }) .catch(err => {}); }); // const index = this.list.indexOf(row) }, //注销 handlerLogoff(row) { api .registerStatusSwitch({ id: row.id, status: row.status == 1 ? 2 : 1 }) .then(res => { this.Register_fetchData(); }) .catch(err => {}); }, //链路删除 Register_handlerDelete(row) { this.$confirm("确定删除吗?", "提示", { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" }).then(() => { let id = row.id; api.VideoTaskDelete(id).then(response => { if (response.code == 200) { this.fetchData(); this.$notify({ title: "成功", message: "删除成功", type: "success", duration: 2000 }); } }); }); }, //链路添加 addRegister() { this.$refs["ruleForm"].validate(valid => { if (valid) { this.Register_dialogFormVisible = true; setTimeout(() => { // this.$refs["AddEdit"].dialogStatus = "create"; // this.$refs.AddEdit.resetTransferDetail(); // this.getCommonData(); }, 1); } else { this.$message.error("基本信息为空不能添加,请先补充基本信息", 6000); } }); }, Register_handleClose() { this.Register_dialogFormVisible = false; }, Register_submitForm() { this.$refs["RegisterAdd"].submitForm(); }, //获取链路注册列表 Register_fetchData() { this.Register_tableLoading = true; api .registerList({ page: 1, page_size: 99999, ip: "" }) .then(res => { console.log("注册列表", res); if (res.code == 200) { this.Register_tableData = res.data.list; this.Register_tableLoading = false; } }) .catch(err => {}); }, handleExceed(files, fileList) { if (files.length > 1) { this.$message.warning( `当前限制最多选择1个文件上传,本次选择了${files.length}个文件` ); } }, //文件上传前的钩子 beforeAvatarUpload(file) { console.log("文件上传前的钩子", file); // 文件类型判断 var testmsg = file.name.substring(file.name.lastIndexOf(".") + 1); const extension = testmsg === "doc"; const extension2 = testmsg === "pdf"; const extension3 = testmsg === "docx"; if (!extension && !extension2 && !extension3) { this.$message({ message: "上传的拓扑图文件只能是word、pdf格式,请重新上传!", type: "error", duration: 6000 }); this.fileList = null; return false; } else { this.fileList = file; } }, //自定义上传 UploadFile() { // 参数拼接 let fileData = new FormData(); fileData.append("file", this.fileList); // 调用接口 axios({ url: `${window.g.API_URL}/api/cascade/topo/upload`, method: "post", data: fileData, headers: { "Content-Type": "multipart/form-data", Authorization: getToken() } }) .then(res => { console.log("上传成功", res); if (res.data.code == 200) { this.tuopuForm = res.data.data; //拓扑预览 this.tuopuPreview(); } else { console.log("上传失败1"); this.$message({ message: "上传拓扑图文件失败,请稍后重试!", type: "error", duration: 6000 }); } }) .catch(err => { console.log("上传失败2", err); this.$message({ message: "上传拓扑图文件失败,请稍后重试!", type: "error", duration: 6000 }); }); }, tuopuPreview() { axios({ url: `${window.g.API_URL}/api/cascade/topo/preview`, method: "get", params: { fileUrl: this.tuopuForm.fileUrl }, headers: { Authorization: getToken() }, responseType: "arraybuffer" }) .then(res => { console.log("拓扑预览获取成功", res); if (res.status == 200) { this.fileList = res.data; } }) .catch(err => { console.log("拓扑预览失败失败", err); }); }, srcChange(val) { console.log("srcChange", val); if (val == this.ruleForm.dstNetwork) { this.ruleForm.dstNetwork = ""; } this.dstList = this.originalList.filter(k => { return k.val != val; }); }, clearSrc() { this.scrList = JSON.parse(JSON.stringify(this.originalList)); }, dstChange(val) { console.log("dstChange", val); if (val == this.ruleForm.srcNetwork) { this.ruleForm.srcNetwork = ""; } this.scrList = this.originalList.filter(k => { return k.val != val; }); }, clearDst() { this.dstList = JSON.parse(JSON.stringify(this.originalList)); } } }; </script> <style lang="scss" scoped> .app-container { .cardWhite { .itemBox { margin-bottom: 1.5rem; .headerTitle { font-size: 1rem; font-weight: bold; } } } } ::v-deep .el-input-number .el-input__inner { text-align: left; } </style>
上传功能实现之后,我们再看预览功能。我们需求是点击预览按钮之后跳到一个新页面进行预览,我先是对文件是否为空是否没上传进行了一个判断拦截,由于预览页面组件与当前页面组件既非父子关系,又非爷孙关系,八竿子打不着的关系,我们就不能通过绑定和sessionStorage来进行流文件的传递,只能在预览页面再发一次请求获取文件流,我们可以把参数通过路由带上,预览按钮对应的方法代码如下:
preview() { console.log("预览", this.fileList, this.tuopuForm); if (!this.fileList) { this.$message.error( "拓扑图文件为空不能预览,请先上传拓扑图文件后再预览", 6000 ); return false; } this.$router.push({ path: "TuotpPreview", query: { fileName: this.tuopuForm.fileName, fileUrl: this.tuopuForm.fileUrl } }); }
再来看预览页面,也就是TuotpPreview.vue组件。word预览比较简单,先通过命令cnpm i docx-preview --save安装插件docx-preview,需要注意的是这个插件只能预览后缀为docx的word文件,如果是doc后缀格式的word文件一定要让后端强制将上传doc格式的文件改为docx格式,然后当前页面组件就直接import { defaultOptions, renderAsync } from “docx-preview”;引入,最后在data里进行docxOptions配置,然后在页面上 要显示的div上绑定一个 id="bodyContainer"的,因为下面要通过document.getElementById来获取dom并操作dom,最后调用renderAsync方法即可。
cnpm i docx-preview --save //安装word预览插件docx-preview import { defaultOptions, renderAsync } from "docx-preview"; //引入docx-preview插件对应的方法 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:启用额外的日志记录 },
pdf文件的预览是通过获取到blob文件流之后,直接通过window.open打开新窗口,通过浏览器就能预览pdf,还有一种就是我现在的这种需求,要在页面上预览pdf,那就需要通过iframe,然后把blob流对应的src地址赋值回显即可。完整代码如下:
<template> <div> <!-- 拓扑图预览 --> <div class="app-container"> <div class="cardWhite"> <div class="topArea"> <div class="backBox"> <img src="@/assets/goBack.png" @click="goBack" alt="" /> </div> <div class="titleBox"> {{ myTitle }} </div> </div> <div class="previewBox"> <div id="bodyContainer"> <iframe :src="pdfUrl" width="100%" height="750px" /> </div> </div> </div> </div> </div> </template> <script> import axios from "axios"; import { getToken } from "@/utils/auth"; import { defaultOptions, renderAsync } from "docx-preview"; export default { data() { return { myTitle: "", previewData: null, 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:启用额外的日志记录 }, num: 1, numPages: 0, pdfUrl: "" }; }, created() { console.log("接收", this.$route.query); this.resetTitle(); this.getFile(); }, methods: { goBack() { this.$router.go(-1); }, //获取文件流 getFile() { axios({ url: `${window.g.API_URL}/api/cascade/topo/preview`, method: "get", params: { fileUrl: this.$route.query.fileUrl }, headers: { Authorization: getToken() }, responseType: "arraybuffer" }) .then(res => { console.log("文件流获取成功", res); if (res.status == 200) { this.previewData = res.data; if ( this.$route.query.fileName && this.$route.query.fileName.indexOf(".docx") && this.$route.query.fileName.indexOf(".pdf") == -1 ) { //word--docx格式 this.wordPreview(res.data); } else if ( this.$route.query.fileName && this.$route.query.fileName.indexOf(".doc") && this.$route.query.fileName.indexOf(".pdf") == -1 ) { //word--doc格式 this.wordPreview(res.data); } else if ( this.$route.query.fileName && this.$route.query.fileName.indexOf(".pdf") ) { //pdf this.pdfPreview(res.data); } } }) .catch(err => { console.log("文件流获取失败", err); this.$message.error("获取文件信息失败,请稍后重试", 6000); }); }, //重置标题 resetTitle() { let fileName = this.$route.query.fileName; console.log("fileName", fileName); if ( fileName && fileName.indexOf(".docx") && fileName.indexOf(".pdf") == -1 ) { //word--docx格式 let wordDocxArr = fileName.split(".docx"); console.log("wordDocxArr", wordDocxArr); this.myTitle = wordDocxArr[0]; } else if ( fileName && fileName.indexOf(".doc") && fileName.indexOf(".pdf") == -1 ) { //word--doc格式 let wordDocArr = fileName.split(".docx"); console.log("wordDocArr", wordDocArr); this.myTitle = wordDocArr[0]; } else if (fileName && fileName.indexOf(".pdf")) { //pdf let pdfArr = fileName.split(".pdf"); console.log("pdfArr", pdfArr); this.myTitle = pdfArr[0]; } }, // word文档预览 wordPreview(buffer) { console.log("文档buffer", 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); }) .catch(err => { console.log("err---->", err); }); }, //pdf预览 pdfPreview(data) { // data是一个ArrayBuffer格式,也是一个buffer流的数据 console.log("pdf流", data); const binaryData = []; binaryData.push(data); //获取blob链接 let pdfUrl = window.URL.createObjectURL( new Blob(binaryData, { type: "application/pdf" }) ); console.log("pdfUrl", pdfUrl); // window.open(pdfUrl); 这种方式是直接打开新浏览器窗口预览 this.pdfUrl = pdfUrl; } } }; </script> <style lang="scss" scoped> .app-container { .cardWhite { display: flex; flex-direction: column; .topArea { display: flex; position: relative; .backBox { margin-bottom: 1rem; img { cursor: pointer; } } .titleBox { text-align: center; background: #fff; color: #000000; position: absolute; top: 0; left: 50%; width: auto; } } } } </style>
以上就是“vue项目怎么实现前端预览word与pdf格式文件”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。