項目上需要用到在線word、excel文檔編輯功能,通過游覽器在線打開一個遠程的word文檔編輯保存,這里記錄下整合思路。
onlyoffice簡介
ONLYOFFICE 是一款開源的辦公套件,提供了一系列在線文檔編輯和協作工具,適用于團隊和個人使用。它支持文檔、表格、演示文稿等格式的創建、編輯和共享,類似于 Google Docs、Microsoft Office 365 等辦公軟件。
官方文檔:https://api.onlyoffice.com/zh-CN/docs/docs-api/get-started/basic-concepts/
onlyoffice部署安裝
使用onlyoffice我們需要先部署一套文檔服務onlyoffice/documentserver
,它是onlyoffice辦公套件的核心組件之一,主要用于處理文檔的在線編輯和協作功能。它是 ONLYOFFICE 的文檔處理服務器,專門負責處理用戶上傳的文檔,支持文檔、表格和演示文稿等格式的在線編輯。
這是部署方式選擇docker,比較簡單一條命令即可:
docker run -i -t -d -p 9097:80 --privileged=true \
--name docserver --restart=always -e TZ=Asia/Shanghai \
-e ALLOW_PRIVATE_IP_ADDRESS=true -e JWT_ENABLED=false \
onlyoffice/documentserver
其中參數JWT_ENABLED=false
是關閉簽名校驗,內網使用的話關掉整合起來會方便些,參數ALLOW_PRIVATE_IP_ADDRESS
是允許內網IP回調,documentserver本身回調我們的業務系統,如果是內網的IP需要設置這個參數,否則默認回調不到,這里我被坑了半天,一直以為是docker網絡配置問題。
VUE整合
這里可以參考官方文檔的這一頁:https://api.onlyoffice.com/zh-CN/docs/docs-api/get-started/frontend-frameworks/vue/
參考文檔按照以下命令可以創建一個vue使用onlyoffice的范例:
# 創建一個名為 _onlyoffice-vue-demo_ 的 Vue.js 3.x 項目
npm create vue@3
# 進入新創建的目錄
cd onlyoffice-vue-demo
# 安裝 ONLYOFFICE 文檔 Vue.js 組件,并使用 _--save_ 將其保存到 _package.json_ 文件中
npm install --save @onlyoffice/document-editor-vue
打開工程將項目中的 ./src/App.vue 文件,并將其內容替換為以下代碼:
<template><DocumentEditor id="docEditor" documentServerUrl="http://192.168.3.96:9097/":config="config":events_onDocumentReady="onDocumentReady":onLoadComponentError="onLoadComponentError"height="900px"/>
</template><script lang="ts">
import { defineComponent } from 'vue';
import { DocumentEditor } from "@onlyoffice/document-editor-vue";export default defineComponent({name: 'ExampleComponent',components: {DocumentEditor},data() {return {config: {document: {fileType: "docx",key: "Khirz6zTPdfd7",title: "這是一個測試文檔",url: "https://home.chengpei.top:8443/root/491f72dd4faa38a214dd8bd1ddb552a9.docx"},documentType: "word",editorConfig: {callbackUrl: "http://192.168.3.213:8080/url-to-callback"},// token: "xxxxxxxxxxxx"}}},methods: {onDocumentReady() {console.log("Document is loaded");},onLoadComponentError (errorCode, errorDescription) {switch(errorCode) {case -1: // Unknown error loading componentconsole.log(errorDescription);break;case -2: // Error load DocsAPI from http://documentserver/console.log(errorDescription);break;case -3: // DocsAPI is not definedconsole.log(errorDescription);break;}}},
});
</script>
這里需要特別注意的幾個參數如下:
documentServerUrl: documentserver服務的URL,也就是上面docker搭建的服務
config: 這是當前要編輯的文檔的描述配置,包含文檔信息(document)、文檔類型(documentType)、編輯配置(editorConfig)、簽名(token)等
callbackUrl: 保存回調地址,當發生編輯器打開、關閉、強制保存等操作時,會回調我們的業務系統執行對應操作,比如保存文件之類的,這是一個我們業務系統必須實現的接口
token: 簽名如果在部署documentserver時配置了JWT_ENABLED=true
則簽名是必須傳的,簽名的計算邏輯參考官方文檔:https://api.onlyoffice.com/zh-CN/docs/docs-api/additional-api/signature/
其中config
參數按理說不應該前端這么寫死的,config
中的參數全都是當前這個待編輯文件的相關信息,應該直接又后端業務系統返回,比如:頁面上展示了一些可編輯文件列表,選擇某個文件點擊編輯時,后端根據原則的文件組裝config信息,包含文件的ID(key)、文件類型(fileType)、文件下載地址(url)等,前端拿到config直接傳給DocumentEditor
組建打開一個onlyoffice的文件編輯窗口即可編輯了,文件編輯過程中是自動保存的,文件有變動馬上會觸發保存,但是這是文件并不是真的保存了,直到窗口關閉了,或者前端調用了強制保存了,documentserver會回調上面配置的callbackUrl
接口,傳入以下請求體:
{"actions": [{"type": "DISCONNECTED","userid": "uid-1756171298433"}],"changesurl": "http://192.168.3.96:9097/cache/files/data/111ac2d8a0815d729fa9_702/changes.zip/changes.zip?md5=Ojhah6-hu1pd_VOr8-uJrA&expires=1756197053&shardkey=undefined&filename=changes.zip","filetype": "docx","history": {"serverVersion": "9.0.4","changes": [{"documentSha256": "fcffb173437380e77bd16661b2a1be0e71c40bb318184acd64da061b3621c186","created": "2025-08-26 08:15:42","user": {"id": "uid-1756171298433","name": "Anonymous"}}]},"key": "111ac2d8a0815d729fa9","status": "SAVE","url": "http://192.168.3.96:9097/cache/files/data/111ac2d8a0815d729fa9_702/output.docx/output.docx?md5=raC8B92ncNB4wcvrRz1CkQ&expires=1756197053&shardkey=undefined&filename=output.docx","users": ["uid-1756171298433"]
}
其中url為修改后的文件,業務系統收到該回調后可以保存該文件,實現業務上的文件保存功能。
前端也可以手動調用接口出發回調強制保存,詳細參考官方文檔命令服務 - forcesave
后端回調接口實現
這里后端使用springboot,實現以下這個接口即可:
@PostMapping(value = "/url-to-callback")
public String callback(@RequestBody final Callback body) {log.info("======== url-to-callback ========");try {String bodyString = JSONUtil.toJsonStr(body);if (bodyString.isEmpty()) { // if the request body is empty, an error occursthrow new RuntimeException("{\"error\":1,\"message\":\"Request payload is empty\"}");}log.info(bodyString);// TODO 判斷當前是什么操作什么狀態,根據情況保存url里的文件} catch (Exception e) {String message = e.getMessage();if (!message.contains("\"error\":1")) {log.error("callback Exception", e);}return message;}return "{\"error\":\"0\"}";
}
Callback
是onlyoffice SDK依賴里的一個類,封裝了回調的參數依賴如下:
<dependency><groupId>com.onlyoffice</groupId><artifactId>docs-integration-sdk</artifactId><version>1.4.0</version>
</dependency>
你也可以在回調地址后面拼上?param=xxx傳一些自定義的參數,通過@RequestParam
拿到