背景
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插件,可以对接文档服务。