背景
onlyoffice —— 在线office系统,可以实现多人在线协作编辑 Word、Excel、PPT等文档。
web在线预览编辑office文档,无需下载文件及桌面软件,编辑实时保存云端。
私有化部署,文档服务器docker部署在自己的服务器,文档等文件也自行存储,保护数据安全。
官方地址:https://www.onlyoffice.com/
工作原理
完整的office在线文档系统包含 文档服务 + 文件管理服务。
- 文档服务:由onlyoffice提供的documentserver实现文档服务,实现word/excel等office文件实时预览编辑,但它不提供文件的永久保存,只是逻辑处理。
- 文件管理服务:负责管理和存储office文件,向文档服务提供具体的文件地址,同时文档编辑完成后异步接收并保存编辑过的文档。此服务可以用PHP定制开发 或使用第三方网盘系统,如NextCloud。
部署文档服务
docker部署
docker run -itd -p 3600:80 \ -v /data/onlyoffice/DocumentServer/logs:/var/log/onlyoffice \ -v /data/onlyoffice/DocumentServer/data:/var/www/onlyoffice/Data onlyoffice/documentserver
- 映射端口和目录根据自身情况修改
docker服务运行后,访问本地IP:端口,如示例 http://192.168.159.128:3600/( 注意: 不能使用 127.0.0.1或localhost,原因不明)
环境要求
社区版 vs 商业版
onlyoffice的社区版是免费的,但限制最多支持20人在线编辑。(网上有些破解版,暂未实测)
文件管理服务
文件管理服务可以通过调用文档服务api,将存储的office文件在线预览编辑。
文件管理服务可以定制开发,或使用第三方网盘系统。
定制开发
官方api文档:https://api.onlyoffice.com/editors/advanced
下面是简单的示例,注意:以下仅是演示代码,不能作为生产代码。
预览office
预览部分的纯前端实现代码:
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <title>office</title> <style> html { height: 100%; width: 100%; } body { background: #fff; color: #333; font-family: Arial, Tahoma,sans-serif; font-size: 12px; font-weight: normal; height: 100%; margin: 0; overflow-y: hidden; padding: 0; text-decoration: none; } form { height: 100%; } div { margin: 0; padding: 0; } </style> </head> <body> <!--关键代码是以下部分--> <div id="placeholder"></div> <script type="text/javascript" src="http://192.168.159.128:3600/web-apps/apps/api/documents/api.js"></script> <script> new DocsAPI.DocEditor("placeholder", { "documentType": "cell", "document": { "fileType": "xlsx", "key" : "Khirz6zTPdfd7888888899911122", "title": "Example Document Title.xlsx", "url": "http://192.168.159.128:8000/example.xlsx", "permissions": { "edit": false, } }, "editorConfig": { "mode": "view", "lang": "zh", "user": { "id": "123456789", "name": "知否", "group": "研发" }, "customization": { "comments": false, "chat": false, } } }); </script> </body> </html>
编辑office
编辑office与预览类似,只是给予了编辑权限并明确指定编辑用户user。
同时,后端需要实现编辑完成后的回调 callback方法。
前端部分代码:
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <title>office</title> <style> html { height: 100%; width: 100%; } body { background: #fff; color: #333; font-family: Arial, Tahoma,sans-serif; font-size: 12px; font-weight: normal; height: 100%; margin: 0; overflow-y: hidden; padding: 0; text-decoration: none; } form { height: 100%; } div { margin: 0; padding: 0; } </style> </head> <body> <!--关键代码--> <div id="placeholder"></div> <script type="text/javascript" src="http://192.168.159.128:3600/web-apps/apps/api/documents/api.js"></script> <script> new DocsAPI.DocEditor("placeholder", { "documentType": "cell", "document": { "fileType": "xlsx", "key" : "Khirz6zTPdfd7000000111222", "title": "Example Document Title.xlsx", "url": "http://192.168.159.128:8000/example1.xlsx", "permissions": { "edit": true, } }, "editorConfig": { "mode": "edit", "lang": "zh", "callbackUrl": "http://192.168.159.128:8000/callback.php", "user": { "id": "123456789", "name": "知否", "group": "研发" }, "customization": { "comments": false, "chat": false, } } }); </script> </body> </html>
后端部分代码:
<?php sendlog('callback start...','callback.log'); $result = [ 'error' => 0, ]; $callback = readBody(); sendlog('callback readBody: '. json_encode($callback), 'callback.log'); if (!empty($callback["error"])){ die(json_encode($callback)); } //保存文件 $status = $callback['status'] ?? 0; switch ($status) { case 1: //编辑中 // todo 用户编辑中 break; case 2: //保存 case 3: save($callback); break; default: break; } die(json_encode($result)); function save($callback) { if (empty($callback['url'])) { return; } file_put_contents('./example1.xlsx',file_get_contents($callback['url']),LOCK_EX); } function sendlog($msg, $logFileName) { $logsFolder = "logs/"; if (!file_exists($logsFolder)) { mkdir($logsFolder); } file_put_contents($logsFolder . $logFileName, $msg . PHP_EOL, FILE_APPEND); } function readBody() { $result["error"] = 0; if (($body_stream = file_get_contents('php://input')) === FALSE) { $result["error"] = "Bad Request"; return $result; } $data = json_decode($body_stream, TRUE); if ($data === NULL) { $result["error"] = "Bad Response"; return $result; } return $data; }
重要参数
文档服务的api中有很多参数和接口,以下是我看到的重要参数:
-
document.key:此参数用来标记文件的唯一性
-
document.url:文件地址,需要是可以访问的url地址
-
editorConfig.user: 编辑用户,多人协作编辑时需标识每个用户信息
其他开发
onlyoffice文档服务提供了诸多接口,根据官方文档实现。
第三方文件管理系统
搭建私有化网盘系统,也可以接入onlyoffice文档服务,实现文档、图片等资源集中管理、控制权限及office在线编辑等功能。
经过测试的开源网盘系统:NextCloud,开源免费,私有化部署,PHP代码方便二次开发。
NextCloud 已有onlyoffice插件,可以对接文档服务。