回调处理程序
文档编辑服务用 JavaScript API 的 callbackUrl 通知文档存储服务有关文档编辑的状态。文档编辑服务使用POST 请求,请求信息在正文中。
参数
| 参数 | 类型 | 描述 |
|---|---|---|
| actions | array of object | 定义当用户对文档执行操作时接收到的对象。type 字段值可以具有以下值: 0 - 用户断开与文档共同编辑的连接, 1 - 新用户连接到文档共同编辑, 2 - 用户单击强制保存按钮。 userid 字段值是用户标识符。 |
| changeshistory | array of object | 定义具有文档更改历史的对象数组。仅当 status 值等于 2 或 3 时,对象才存在。 必须作为对象的属性 changes 以参数形式发送给 refreshHistory 方法。自 4.2 版起已删除,请改用 history。 |
| changesurl | string | 使用文档编辑数据定义文件的链接,用于跟踪和显示文档更改历史记录。仅当 status 等于 2, 3, 6 或 7 时,链接才存在。必须保存文件,并且必须使用 setHistoryData 方法将其地址作为 changesUrl 参数发送,以显示与特定文档版本对应的更改。 |
| filetype | string | 定义从 url 参数指定的链接下载文档的扩展名。文件类型默认为 OOXML,但如果启用了 assemblyFormatAsOrigin 服务器设置,则文件将以原始格式保存。 |
| forcesavetype | integer | 定义执行强制保存请求时的启动器类型。可以有以下值: 0 - 为命令服务执行强制保存请求, 1 - 每次保存完成时都会执行强制保存请求(例如单击 保存 按钮),这仅在 forcesave 选项设置为 true时可用, 2 - 强制保存请求由计时器按服务器配置中的设置执行, 3 - 每次提交表单时都会执行强制保存请求 Complete & Submit 按钮被点击 )。 该类型仅在 status 值等于 6 或 7 时出现。 |
| formsdataurl | object | 用提交的表单数据,定义 JSON 文件的 URL。此处描述了包含表单数据的数组结构。当 status 值等于 6 并且 forcesavetype 值等于 3 时,该对象才存在。 |
| formsdataurl.key | string | 表单键。 如果当前表单是单选按钮,则该字段包含表单组键。 |
| formsdataurl.tag | string | 表单标签。 |
| formsdataurl.value | string | 当前表单值。 |
| formsdataurl.type | string | 表单类型 (text, checkBox, picture, comboBox, dropDownList, dateTime, radio)。 |
| history | object | 定义有文档更改历史的对象。仅当 status 值等于 2 或 3 时,对象才存在。它包含对象 changes 和 serverVersion,它们必须作为对象的属性 changes 和 serverVersion 以参数形式发送给 refreshHistory 方法。 |
| key* | string | 定义编辑的文档标识符。 |
| status* | integer | 定义文档的状态。可以有以下值: 1 - 正在编辑文档, 2 - 文档已准备好保存, 3 - 发生文档保存错误, 4 - 文档已关闭,没有任何更改, 6 - 正在编辑文档,但保存了当前文档状态, 7 - 强制保存文档时发生错误。 |
| url | string | 定义已编辑的要由文档存储服务保存的文档的链接。仅当 status 值等于 2, 3, 6 或 7 时,链接才存在。 |
| userdata | string | 定义发送到 forcesave 和 info 命令的命令服务的自定义信息(如果它在请求中存在)。 |
| users | array of string | 定义打开文档进行编辑的用户的标识符列表;当文档被更改时,用户将返回最后编辑文档的用户的标识符(对于 status 2 和 status 6 的应答)。 |
* - 必需参数
服务器存储所有callbackUrl,并根据执行操作的用户选择使用哪一个。
从 5.5 版本开始,根据请求的 status 选择 callbackUrl。从 4.4 到 5.5 版本,callbackUrl 来自最后一个加入共同编辑的用户。在 4.4 之前的版本中,在共同编辑时,callbackUrl 来自第一次打开文件进行编辑的用户。
从 7.0 版开始,callbackUrl 来自同一用户的最后一个标签。在 7.0 版之前,callbackUrl 来自第一个用户标签。
可能的文档状态及其描述
状态 1
每次用户连接或断开文档共同编辑时都会收到它。他们的 callbackUrl 被使用。
请注意,当用户在遭遇Internet 故障后返回到没有更改的文档时也可以收到 status 1。这种情况可以描述如下:
- 当用户打开文档时,会发送 status 1。
- 如果 Internet 连接丢失并且用户没有对文档进行任何更改,则会发送 status 4。屏幕上显示错误并在查看器中打开文档。
- 在 100 秒内,互联网连接恢复,用户重新连接到文档并再次发送 status 1。
- 现在用户可以继续编辑文档。将收到 status 2 或 4,具体取决于用户是否对文档进行了任何更改。
状态 2 (3)
它在编辑文档关闭后 10 秒收到,该用户的标识符是最后一个将更改发送到文档编辑服务的用户。对文件进行最后更改的用户的 callbackUrl 被使用。
Status 4
它是在最后一个用户关闭所编辑的没有更改的文档情况下收到的。他们的 callbackUrl 被使用。
状态 6 (7)
在执行强制保存请求时接收到。callbackUrl 依赖于 forcesavetype 参数:
- 如果 forcesavetype 参数设置为 1,则使用点击 保存 按钮的用户的 callbackUrl。
- 如果 forcesavetype 参数设置为 0 或 2,则使用对文件进行最后更改的用户的 callbackUrl。
- 如果 forcesavetype 参数设置为3,则使用点击 提交 按钮的用户的 callbackUrl。从版本 5.5 到版本 6.1,始终使用对文件进行最后更改的用户的 callbackUrl。
请求示例
当两个用户共同编辑文档时,文档编辑服务发送到"callbackUrl"地址的 JSON 对象示例
{
"actions": [
{"type": 1,
"userid": "78e1e841"}
],
"key": "Khirz6zTPdfd7",
"status": 1,
"users": ["6d5a81d0", "78e1e841"]
}
当用户更改文档并关闭编辑的文档时,文档编辑服务发送到"callbackUrl"地址的 JSON 对象示例
{
"actions": [
{
"type": 0,
"userid": "78e1e841"
}
],
"changesurl": "https://documentserver/url-to-changes.zip",
"history": {
"changes": changes,
"serverVersion": serverVersion
},
"filetype": "docx",
"key": "Khirz6zTPdfd7",
"status": 2,
"url": "https://documentserver/url-to-edited-document.docx",
"users": ["6d5a81d0"]
}
当最后一个用户关闭编辑的无更改的文档时,文档编辑服务发送到 "callbackUrl" 地址的 JSON 对象示例
{
"key": "Khirz6zTPdfd7",
"status": 4
}
接收到 forcesave 命令后文档编辑服务发送到 "callbackUrl" 地址的JSON对象示例
{
"changesurl": "https://documentserver/url-to-changes.zip",
"forcesavetype": 0,
"history": {
"changes": changes,
"serverVersion": serverVersion
},
"filetype": "docx",
"key": "Khirz6zTPdfd7",
"status": 6,
"url": "https://documentserver/url-to-edited-document.docx",
"users": ["6d5a81d0"],
"userdata": "sample userdata"
}
来自文档存储服务的响应
文档存储服务必须返回以下响应,否则文档编辑器将显示错误消息:
{
"error": 0
}
文档管理器和文档存储服务要么包含在社区版服务器中,要么必须由在自己的服务器上使用 ONLYOFFICE 文档的软件集成商实施。
文档保存示例
- .Net (C#)
- Java
- Node.js
- PHP
- Ruby
public class WebEditor : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string body;
using (var reader = new StreamReader(context.Request.InputStream))
body = reader.ReadToEnd();
var fileData = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(body);
if ((int) fileData["status"] == 2)
{
var req = WebRequest.Create((string) fileData["url"]);
using (var stream = req.GetResponse().GetResponseStream())
using (var fs = File.Open(PATH_FOR_SAVE, FileMode.Create))
{
var buffer = new byte[4096];
int readed;
while ((readed = stream.Read(buffer, 0, 4096)) != 0)
fs.Write(buffer, 0, readed);
}
}
context.Response.Write("{\"error\":0}");
}
}
PATH_FOR_SAVE is the absolute path to your computer folder where the file will be saved including the file name.
On the .Net example page, you will learn how to integrate ONLYOFFICE Docs into your web application written on .Net (C#) or .Net (C# MVC).
public class IndexServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter writer = response.getWriter();
Scanner scanner = new Scanner(request.getInputStream()).useDelimiter("\\A");
String body = scanner.hasNext() ? scanner.next() : "";
JSONObject jsonObj = (JSONObject) new JSONParser().parse(body);
if((long) jsonObj.get("status") == 2)
{
String downloadUri = (String) jsonObj.get("url");
URL url = new URL(downloadUri);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
InputStream stream = connection.getInputStream();
File savedFile = new File(pathForSave);
try (FileOutputStream out = new FileOutputStream(savedFile)) {
int read;
final byte[] bytes = new byte[1024];
while ((read = stream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
}
connection.disconnect();
}
writer.write("{\"error\":0}");
}
}
pathForSave is the absolute path to your computer folder where the file will be saved including the file name.
On the Java example and Java integration SDK pages, you will learn how to integrate ONLYOFFICE Docs into your web application written on Java.
import {fs} from "node:fs";
import {syncRequest} from "sync-request";
app.post("/track", (req, res) => {
function updateFile(response, body, path) {
if (body.status === 2) {
const file = syncRequest("GET", body.url);
fs.writeFileSync(path, file.getBody());
}
response.write("{\"error\":0}");
response.end();
}
function readbody(request, response, path) {
let content = "";
request.on("data", (data) => {
content += data;
});
request.on("end", () => {
const body = JSON.parse(content);
updateFile(response, body, path);
});
}
if (req.body.hasOwn("status")) {
updateFile(res, req.body, pathForSave);
} else {
readbody(req, res, pathForSave);
}
});
pathForSave is the absolute path to your computer folder where the file will be saved including the file name.
On the NodeJS example page, you will learn how to integrate ONLYOFFICE Docs into your web application written on Node.js.
<?php
if (($body_stream = file_get_contents("php://input"))===FALSE){
echo "Bad Request";
}
$data = json_decode($body_stream, TRUE);
if ($data["status"] == 2){
$downloadUri = $data["url"];
if (($new_data = file_get_contents($downloadUri))===FALSE){
echo "Bad Response";
} else {
file_put_contents($path_for_save, $new_data, LOCK_EX);
}
}
echo "{\"error\":0}";
?>
$path_for_save is the absolute path to your computer folder where the file will be saved including the file name.
On the PHP example page, you will learn how to integrate ONLYOFFICE Docs into your web application written on PHP.
class ApplicationController < ActionController::Base
def index
body = request.body.read
file_data = JSON.parse(body)
status = file_data["status"].to_i
if status == 2
download_uri = file_data["url"]
uri = URI.parse(download_uri)
http = Net::HTTP.new(uri.host, uri.port)
if download_uri.start_with?("https")
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
req = Net::HTTP::Get.new(uri.request_uri)
res = http.request(req)
data = res.body
File.open(path_for_save, "wb") do |file|
file.write(data)
end
end
render :text => "{\"error\":0}"
end
end
path_for_save is the absolute path to your computer folder where the file will be saved including the file name.
On the Ruby example page, you will learn how to integrate ONLYOFFICE Docs into your web application written on Ruby.