Vue 预览word,excel等office

先看效果!!
在这里插入图片描述
在这里插入图片描述

需求背景:在前端页面中预览office文件且是内网访问,服务器不可访问外网的前提。 因此微软的接口就废掉了,因为他接口的条件是可以访问外网。

在找了很多家demo中决定使用onlyoffice这一方案:

1.安装onlyoffice docker
本人为前端小白,安装这种东西不太熟悉,可以去官网看一下 有傻瓜式教程。链接:onlyoffice
我这边是后端大佬已经安装好了

2.引入onlyoffice
在项目的public目录下面的index.html文件中引用
src后面为onlyoffice服务器的地址,进行完第一步之后就可以拿到
在这里插入图片描述

<script type='text/javascript' src='http://服务地址/web-apps/apps/api/documents/api.js'></script>

3.封装一个vue组件
新建一个vue文件

<template>
  <div id='vabOnlyOffice'></div>

</template>

<script>
  import { getFileType } from '@/utils/wayne'

  export default {
    name: 'VabOnlyOffice',
    props: {
      option: {
        type: Object,
        default: () => {
          return {}
        },
      },
    },
    data() {
      return {
        doctype: '',
        //参数说明
        parameters: {
          'document': {
            //文件扩展名
            'fileType': 'docx',
            //key 默认置空则不走缓存 always update
            'key': '',
            //为已查看或编辑的文档定义所需的文件名,该文件名在下载文档时也将用作文件名。
            'title': '',
            //文件地址
            'url': '',
            //相关权限
            'permissions': {
              'copy': true,//定义内容是否可以复制到剪贴板。如果该参数设置为false,则只能在当前文档编辑器中粘贴内容。默认值为true。
              'download': true,//定义文档是可以下载还是只能在线查看或编辑。如果下载权限设置为“假”的下载为...菜单选项将是缺席的文件菜单。默认值为true。
              'edit': true,//定义文档是可以编辑还是只能查看。如果编辑权限设置为“true”,则文件菜单将包含编辑文档菜单选项;请注意,如果编辑权限设置为“false”,文档将在查看器中打开,即使模式参数设置为edit,您也无法将其切换到编辑器。默认值为true。
              'print': true,//定义是否可以打印文档。如果打印权限设置为“false”的打印菜单选项将是缺席的文件菜单。默认值为true
            },
          },
          //文件类型
          'documentType': 'text',
          'height': '100%',
          'width': '100%',
          'editorConfig': {
            //语言:zh-CN简体中文/en英文
            'lang': 'zh-CN',
            //阅读状态 view/edit
            'mode': 'view',
            'customization': {
              //是否显示插件
              'plugins': false,
            },
          },
        },
      }
    },
    watch: {
      option: {
        handler: function(n) {
          this.setEditor(n)
          this.doctype = getFileType(n.fileType)
        },
        deep: true,
      },
    },
    mounted() {
      if (this.option.url) {
        this.setEditor(this.option)
      }
    },
    methods: {
      async setEditor(option) {
        this.doctype = getFileType(option.fileType)

        let config = {
          document: {
            //后缀
            fileType: option.fileType,
            key: '',
            title: option.title,
            permissions: {
              edit: option.isEdit,//是否可以编辑: 只能查看,传false
              print: option.isPrint,
              download: false,
              // "fillForms": true,//是否可以填写表格,如果将mode参数设置为edit,则填写表单仅对文档编辑器可用。 默认值与edit或review参数的值一致。
              // "review": true //跟踪变化
            },
            url: option.url,
          },
          documentType: this.doctype,
          editorConfig: {
            callbackUrl: option.editUrl,//"编辑word后保存时回调的地址,这个api需要自己写了,将编辑后的文件通过这个api保存到自己想要的位置
            lang: option.lang,//语言设置
            //定制
            customization: {
              autosave: false,//是否自动保存
              chat: false,
              comments: false,
              help: false,
              // "hideRightMenu": false,//定义在第一次加载时是显示还是隐藏右侧菜单。 默认值为false
              //是否显示插件
              plugins: false,
              //暂时无法生效
              customer: {
                address: '12333333333',
                info: 'S11',
                logo: '123',
                mail: 'j123',
                name: '123',
                www: '123',
              },
            },
          },
          width: '100%',
          height: '100%',
        }

        // eslint-disable-next-line no-undef,no-unused-vars
        new DocsAPI.DocEditor('vabOnlyOffice', config)

      },
    },
  }
</script>


更多的参数说明可以参考官方文档,常用就以上例子

在此特别说明一下这个token的问题
花费了大量的时间发现。参数中的token 并不是 你请求文件时候所使用的token 而是用作于 请求到onlyoffice的这个过程中使用的token。
这个token默认是关闭的。 可以通过修改工程文件设置为打开,不过觉得没必要,因为他都是内网的。
而onlyoffice到你的服务端的请求中 也附带了token 经过大量查询发现 是他自己将config中的部分内容以JWT形式加密 然后附在头部请求中,

给人的假象就像是 配置文件中的token就是 一般请求的token 然鹅并不是!!

简单来说 url 为请求文件地址 前端为A onlyoffice为B 后端为C
整个过程是 A–B B–C
配置文件中的token 用作与A–B
但是B–C 也有token 但是这个token(似乎是不可修改的,如果有大佬解开了请麻烦联系下我,求解) 不可修改, 就导致了这个token 会影响到本身应有的token.
解决方案是:文件服务废弃token, ( 爷不用了还不行吗,) 如果考虑安全性(都是内网 大可不必), 可以获取一个KEY 拼接在url中。以此替代token

3.调用组件

<template>
  <div class='qualityManual-container'>
    <el-row>
      <el-col :span='24'>
        <div>
          <el-button style='width: 120px;' type='primary' @click='getFile'>测试预览office文档</el-button>
          <el-button style='width: 120px;' type='primary' @click='close'>关闭</el-button>
        </div>
        <div v-if='show' class='qualityManual-container-office'>
          <vab-only-office :option='option' />
        </div>
      </el-col>
    </el-row>
  </div>


</template>

<script>
  import vabOnlyOffice from '@/vab/components/VabOnlyOffice'

  export default {
    name: 'QualityManual',
    components: { vabOnlyOffice },
    data() {
      return {
        //参考vabOnlyOffice组件参数配置
        option: {
          url: '',
          isEdit: '',
          fileType: '',
          title: '',
          lang: '',
          isPrint: '',
        },
        show: false,
      }
    },
    methods: {
      getFile() {
        this.show = true
        // getAction('/onlyfile/file/queryById', { id: this.id }).then(res => {
        this.option.isEdit = false
        this.option.lang = 'zh-CN
        this.option.url = 'http://192.168.3.71:8002/lis/file/download/getDocumentFileByUrl?url=/测试word.docx'
        this.option.title = '123'
        this.option.fileType = 'docx'
        this.option.isPrint = false
        // })
      },
      close() {
        this.show = false
      },
    },
  }
</script>

<style lang='scss' scoped>

  .qualityManual-container {
    padding: 0 !important;
    
    &-office {
      width: 100%;
      height: calc(#{$base-keep-alive-height-tc} - 55px);
    }

  }

</style>

<vab-only-office :option='option' />

这就是刚刚封装的组件
可以设置父级的样式来控制页面的大小

&-office {
      width: 100%;
      height: calc(#{$base-keep-alive-height-tc} - 55px);
    }

4.外部方法
util中的方法

//返回文件格式
export function getFileType(fileType) {
  let docType = ''
  let fileTypesDoc = [
    'doc', 'docm', 'docx', 'dot', 'dotm', 'dotx', 'epub', 'fodt', 'htm', 'html', 'mht', 'odt', 'ott', 'pdf', 'rtf', 'txt', 'djvu', 'xps',
  ]
  let fileTypesCsv = [
    'csv', 'fods', 'ods', 'ots', 'xls', 'xlsm', 'xlsx', 'xlt', 'xltm', 'xltx',
  ]
  let fileTypesPPt = [
    'fodp', 'odp', 'otp', 'pot', 'potm', 'potx', 'pps', 'ppsm', 'ppsx', 'ppt', 'pptm', 'pptx',
  ]
  if (fileTypesDoc.includes(fileType)) {
    docType = 'text'
  }
  if (fileTypesCsv.includes(fileType)) {
    docType = 'spreadsheet'
  }
  if (fileTypesPPt.includes(fileType)) {
    docType = 'presentation'
  }
  return docType
}

经测试,适用于word,excel,ppt,pdf格式文件的预览

Logo

前往低代码交流专区

更多推荐