Onlyoffice 二次开发指南

3,064 阅读8分钟

缘起于进行了一次在线 Office 解决方案的调研,对比了 Office365、可道云、WPS Office、PageOffice 等厂商,最终敲定了使用 Onlyoffice,故整理了一份 Onlyoffice 从零开始系列教程,这是第二篇。

本篇文章提到的代码片段和预览效果均在 demo-onlyoffice Github,克隆后对照查看会有更好的阅读体验。

自定义 Onlyoffice 配置

第一篇中已经介绍了如何在 Vue.js 中接入 Onlyoffice,这里不再赘述。接下来自定义配置实现:编辑器语言设置为中文、添加当前编辑的用户信息、文档编辑后支持保存等。

还是那核心的三步,添加容器、引入入口 JS 文件、初始化 Onlyoffice 实例,前两步都不变,只是在第三步时,传入新的编辑器配置:

// 编辑器配置项,完整配置项参见:https://api.onlyoffice.com/editors/config/
const editorConfig = {
  // 编辑器宽度,也可以设置成百分比,不过要父容器设定具体宽度
  width: 1200,
  // 编辑器高度
  height: 800,
  // 编辑器类型,支持 word、cell(表格)、slide(PPT)
  documentType: 'word',
  // 文档配置
  document: {
    // 当前文档类型
    fileType: 'docx',
    // 文档标识符
    key: 'test2.docx',
    // 文档地址,绝对路径
    url: url: 'http://IP/static/test2.docx',,
    // 文档标题
    title: '测试文档二.docx',
    // 权限,每个要打开的文档都可以设置独立的权限
    permissions: {
      // 启用评论
      comment: false,
      // 启用下载
      download: true,
      // 启用编辑
      edit: true,
      // 启用导出
      print: true,
      // 启用预览
      review: true
    }
  },
  editorConfig: {
    // 回调地址
    callbackUrl: 'http://IP/api/v1/onlyoffice/callback',
    // 设置语言
    lang: 'zh-CN',
    // 添加用户信息
    user: {
      group: '技术部', id: 'wytxer', name: '程序员未央'
    },
    // 模板列表
    templates: [],
    // customization 字段相关配置详解:https://api.onlyoffice.com/editors/config/editor/customization
    customization: {
      // 强制保存
      forcesave: true,
      features: {
        // 关闭拼写检查
        spellcheck: false
      }
    }
  }
}

其中的 editorConfig.lang 配置项表示国际化配置,设置为 zh-CN,表示中文。

其中的 editorConfig.user 配置项表示用户信息,可以是业务上的用户体系信息,group 配置项表示组织,在协同编辑时显示的用户名也是在这里设置的。

而其中的 editorConfig.callbackUrl 配置项表示文档编辑服务的回调配置,就是这个配置实现了文档编辑后的保存。

最后实现效果如下:

那么,Onlyoffice 中的文档编辑后是怎么保存到业务服务器的呢?

如上图,文档编辑器和文档编辑服务都是 Onlyoffice 提供的(除此之外,Onlyoffice 里面还有文档存储服务、文档转换服务、文档生成器服务、文档指令服务等),而文档存储服务则是业务中自定义的。

当用户编辑文档时,浏览器文档编辑服务,编辑结束时文档编辑服务合并变更并通过 callbackUrl 通知文档存储服务文档编辑结束,并返回修改后文档的链接,文档存储服务根据返回的文档链接从文档编辑服务下载文档并将其存储。

所以每次编辑完成时,callbackUrl 都会收到 Onlyoffice 文档编辑服务传递过来的文档信息,里面除了新的文档链接外,还包含了用户与文档的交互状态、文档标识符、文档强制保存类型等字段(可在 Onlyoffice callbackUrl 介绍看到完整的回调参数说明)。callbackUrl 拿到这些回调参数后根据文档状态进行文档保存操作:

const { url, status } = body
// 正在编辑文档但保存了当前文档状态
if (status === 6) {
  try {
    // 保存文档最核心的 3 行代码
    // 1、根据文档链接地址下载文档文件
    const file: AxiosResponse = await this.request.axiosRef.get(url, {
      responseType: 'stream'
    })
    // 2、创建可写流
    const stream: WriteStream = createWriteStream(
      // 将文档文件保存到磁盘目录,这里是一个绝对路径,例如 /var/opt/onlyoffice/files/test2.docx
      join(this.config.get('staticPath'), body.key)
    )
    // 3、写入文档文件
    file.data.pipe(stream)
  } catch (error) {
    // 保存出错
  }
} else if (status === 7) {
  // 强制保存文档出错
}

这里最核心的就是 try 函数里面的 3 行代码,合起来实现了根据文档链接下载文档并保存到服务器

当前示例页面访问路径:http://127.0.0.1:3001/onlyoffice/document/custom-config

接口获取 Onlyoffice 配置

上面的实现方式,配置项是写在前端的,而真实的业务中,建议配置项通过后端获取。

那么后端维护配置项有什么好处呢?我总结了两点:

  • 便于维护。因为文档一般与业务场景绑定,会包含一些业务字段,而且可能每个文档都有不同的权限配置,前端来维护,就要维护每个文档对应的权限,明显不合适。
  • 可以更方便使用 Onlyoffice 提供的 JWT(JSON Web Token)加密,增强安全性。

实现起来也不复杂,我们先将前端 Onlyoffice 实例化部分封装到组件(具体实现可参见 views/onlyoffice/modules/onlyoffice-editor.vue),外部只需要传递获取到的 Onlyoffice 配置项即可:

<onlyoffice-editor :config="editorConfig" />

后端接口实现上,将编辑器配置和业务字段合并返回:

// Onlyoffice 编辑器配置项
const editorConfig = {
  width: 1200,
  height: 800,
  documentType: 'word'
  // ...
}
// 最终接口返回的字段信息
return {
  id: 1,
  remarks: '业务字段',
  editorConfig
}

具体实现可参见 onlyoffice-server/src/document/document.controller.ts 里面的 documentInfo 方法。

当前示例页面访问路径:http://127.0.0.1:3001/onlyoffice/document/editor

使用 JWT 加密 Onlyoffice 配置

Onlyoffice 服务支持配置 JWT 加密提升服务安全性。那么,如何开启 Onlyoffice 的 JWT 加密呢?

通过修改 Onlyoffice 提供的配置文件即可开启 JWT 加密,配置文件在系统中的位置如下:

Linux 配置文件路径:/etc/onlyoffice/documentserver/local.json
Windows 配置文件路径:%ProgramFiles%\ONLYOFFICE\DocumentServer\config\local.json

1、我们先从 Onlyoffice 下载默认的配置项:

# 注意把 id 替换成自己的
docker cp id:/etc/onlyoffice/documentserver/local.json ./

2、保留一份 local.json 副本,然后将以下配置项覆盖到 local.json

{
  "services": {
    "CoAuthoring": {
      "sql": {
        "type": "postgres",
        "dbHost": "localhost",
        "dbPort": "5432",
        "dbName": "onlyoffice",
        "dbUser": "onlyoffice",
        "dbPass": "onlyoffice"
      },
      "token": {
        "enable": {
          "request": {
            "inbox": true,
            "outbox": true
          },
          "browser": true
        },
        "inbox": {
          "header": "AuthorizationJwt",
          "inBody": true
        },
        "outbox": {
          "header": "AuthorizationJwt",
          "inBody": true
        }
      },
      "secret": {
        "inbox": {
          "string": "123456"
        },
        "outbox": {
          "string": "123456"
        },
        "session": {
          "string": "123456"
        }
      }
    }
  },
  "rabbitmq": {
    "url": "amqp://guest:guest@localhost"
  }
}

如上 JSON 配置,其中的 services.CoAuthoring.token.enable 字段配置要开启加密的端和方式,这里默认全部开启,services.CoAuthoring.secret 字段配置秘钥,这里全部设置为 123456

3、然后执行下面这个命令上传 local.json 文件

# 注意把 id 替换成自己的。这一步会覆盖 Onlyoffice 服务里面的默认配置,建议先做好备份方便恢复
docker cp local.json id:/etc/onlyoffice/documentserver/ && docker exec -it id /bin/bash -c "supervisorctl restart all"

一切正常应该会有以下输出:

然后刷新使用 JWT 加密 Onlyoffice 配置示例页面,可以看到获取到的数据里面已经带了 token 参数:

onlyoffice-browser-token.png

后端调用指令服务也进行了 JWT 加密:

// 如果是使用了 JWT 加密,重新组装请求参数
if (useJwtEncrypt === 'y') {
  newBody = {
    token: this.jwt.sign(newBody, {
      secret: this.config.get('onlyoffice.secret')
    })
  }
}

而这个时候如果去访问其他的示例就会看到如下报错:

当前示例页面访问路径:http://127.0.0.1:3001/onlyoffice/document/editor-jwt

Onlyoffice 文档转换功能介绍

Onlyoffice 支持不同文档类型之间相互转换,比如将 docx 格式的文件转成 pdf 格式。以下是各个文档类型之间转换的对照表:

想要使用这个功能,只需要调用 Onlyoffice 提供的转换 API https://documentserver/ConvertService.ashx (documentserver 表示安装了 Onlyoffice 的服务器地址)即可。

例如将 html 格式的文件转换成 docx,请求示例:

onlyofficeConversion({
  // 请求参数详解:https://api.onlyoffice.com/editors/conversionapi
  async: false,
  // 当前要转换的文档类型
  filetype: 'html',
  // 最终要输出的文档类型
  outputtype: 'docx',
  // 文档地址
  url: 'http://IP/static/test5.html',
  // 文档名称
  key: 'test5.html'
})
  .then(res => {
    // res.endConvert 返回 true,表示文档转换成功
    if (res.endConvert) this.$message.success('转换成功')
  })
  .finally(() => {
    this.loading.toDocx = false
  })

接口响应结果示例:

{
  "fileUrl": "http://127.0.0.1:3001/cache/files/conv_test5.html_docx/output.docx/output.docx?md5=3sOj9_vDJTc5HVTVQFU7bw&expires=1661184550&filename=output.docx",
  "fileType": "docx",
  "percent": 100,
  "endConvert": true
}

当前示例页面访问路径:http://127.0.0.1:3001/onlyoffice/document/conversion

Onlyoffice 文档生成器功能介绍

Onlyoffice 的文档生成器服务,实现了一套文档构建语法,支持写代码的方式来生成文档。

文档构建语法形似 JavaScript API:

// 要生成的文档类型
builder.CreateFile("docx")
// 文档对象
var oDocument = Api.GetDocument()

// 在文档对象上创建一个元素
var oParagraph = oDocument.GetElement(0)
// 设置元素的文本内容为「标题」
oParagraph.AddText("标题")
// 设置元素文本的对齐方式
oParagraph.SetJc("center")
// 设置元素字体大小
oParagraph.SetFontSize(40)
// 设置元素字体
oParagraph.SetFontFamily("Arial")

不过最终的文件后缀是 docbuilder,例如 test1.docbuilder。

更多文档构建语法参见这里:Onlyoffice Builder API

最终文档转换是通过文档构建器服务提供的转换 API:https://documentserver/docbuilder (documentserver 表示安装了 Onlyoffice 的服务器地址)

这里以将 test1.docbuilder 文件转成 docx 格式为例,请求示例:

onlyofficeBuilder({
  // 请求参数详解:https://api.onlyoffice.com/editors/documentbuilderapi
  async: false,
  // 当前语法文件路径
  url: 'http://IP/static/docbuilder/test1.docbuilder'
})

接口响应结果示例:

{
  "key": "bld_e6f134f281a3cb8b",
  "urls": {
    "test1.docx": "http://127.0.0.1:3001/cache/files/bld_e6f134f281a3cb8b/output/test1.docx/test1.docx?md5=f-wyC4a-Hs0wjHR3FXhscQ&expires=1661185765&filename=test1.docx"
  },
  "end": true
}

当前示例页面访问路径:http://127.0.0.1:3001/onlyoffice/document/conversion

在 Vue 中 集成 Onlyoffice Excel 编辑器

Onlyoffice 除了 Word 编辑器外,还支持 Excel 和 PPT 编辑器。与集成 Word 编辑器只有少数地方不同,这里以集成 Excel 编辑器为例:

1、文档配置不同:

editorConfig.document = {
  fileType: 'xlsx',
  key: 'test1.xlsx',
  url: 'http://IP//static/test1.xlsx',
  title: '测试表格.xlsx'
}

2、编辑器类型配置不同:

editorConfig.documentType = 'cell'

集成后效果如下:

onlyoffice-excel-formula.png

当前示例页面访问路径:

使用 onlyoffice-vue 组件

基于 Vue.js 2.x 封装了一个 onlyoffice-vue 组件,支持异步加载 api.js、支持自定义 Onlyoffice 配置项、一个页面加载多个编辑器等。

1、安装

pnpm add onlyoffice-vue

2、使用

<template>
  <onlyoffice-editor :src="src" :config="editorConfig" @ready="onReady" />
</template>

<script>
export default {
  data () {
    return {
      src: 'http://IP/web-apps/apps/api/documents/api.js',
      editorConfig: {
        document: {
          fileType: 'docx',
          key: 'key.docx',
          title: '测试.docx',
          url: 'http://IP/static/test.docx'
        },
        editorConfig: {
          callbackUrl: 'http://IP/api/v1/onlyoffice/callback'
        }
      }
    }
  },
  methods: {
    // 编辑器加载完毕后回调 ready 函数,editor 为当前编辑器实例
    onReady (editor) {}
  }
}
</script>

当前示例页面访问路径:http://127.0.0.1:3001/onlyoffice/document/onlyoffice-vue

更多功能

除了上面介绍的一些使用方式和功能外,Onlyoffice 还支持自定义历史记录、协同编辑、插件开发等能力,想要了解更多可到 Onlyoffice API 查看。