0


vue项目实现前端预览word和pdf格式文件

最近做vue项目遇到一个需求,就是前端实现上传word或pdf文件后,后端返回文件对应的文件流,前端需要在页面上展示出来。word预览简单一些,pdf预览我试过pdfjs,vue-pdf总是报各种奇奇怪怪的bug,但最终总算解决了问题,先看一下页面最终呈现效果吧:

页面上传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="请选择链路类型"
                  style="width:100%"
                  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="请选择"
                      style="width:100%"
                      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 style="text-align: center;width:100%"><img
                        src="@/assets/toRight.png"
                        style="width:3.75rem;height:0.75rem;margin:0 auto"/></div></el-col><el-col :span="10"><el-select
                      v-model="ruleForm.dstNetwork"
                      placeholder="请选择"
                      style="width:100%":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"
                  style="width:100%"></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"
                      style="background:#1890ff;color:#fff;border-top-left-radius:0;border-bottom-left-radius:0">上传</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" style="margin:0.5rem 0;"><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'])"
                style="margin-left:-0.015rem">删除</el-button
              ></template></commonTable></div></div><div class="itemBox"><div class="headerTitle">链路注册</div><el-row type="flex" justify="end" style="margin:0.5rem 0;"><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)"
                style="margin-left:-0.015rem">删除</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";exportdefault{components:{
    Pagination,
    commonTable,
    AddEdit,
    RegisterAdd
  },data(){constvalidateGo=(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);returnfalse;}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;returnfalse;}else{this.fileList = file;}},//自定义上传UploadFile(){// 参数拼接let fileData =newFormData();
      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);returnfalse;}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-previewimport{ 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.createObjectURLuseMathMLPolyfill: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";exportdefault{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.createObjectURLuseMathMLPolyfill: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);}elseif(this.$route.query.fileName &&this.$route.query.fileName.indexOf(".doc")&&this.$route.query.fileName.indexOf(".pdf")==-1){//word--doc格式this.wordPreview(res.data);}elseif(this.$route.query.fileName &&this.$route.query.fileName.indexOf(".pdf")){//pdfthis.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];}elseif(
        fileName &&
        fileName.indexOf(".doc")&&
        fileName.indexOf(".pdf")==-1){//word--doc格式let wordDocArr = fileName.split(".docx");
        console.log("wordDocArr", wordDocArr);this.myTitle = wordDocArr[0];}elseif(fileName && fileName.indexOf(".pdf")){//pdflet 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(newBlob(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.js word

本文转载自: https://blog.csdn.net/qq_37635012/article/details/128298394
版权归原作者 百思不得小李 所有, 如有侵权,请联系我们删除。

“vue项目实现前端预览word和pdf格式文件”的评论:

还没有评论