From 6a77c800d56c6b4c3260c1b74ea7798d84f98ad8 Mon Sep 17 00:00:00 2001
From: linwei <872216696@qq.com>
Date: Fri, 10 Jul 2026 08:38:51 +0800
Subject: [PATCH] feat(resource): 集成OnlyOffice文档编辑功能
---
drone-ops/drone-resource/src/main/java/org/sxkj/resource/endpoint/OfficeCallbackEndpoint.java | 134 +++++++++++++++++++++++++++++---------------
1 files changed, 87 insertions(+), 47 deletions(-)
diff --git a/drone-ops/drone-resource/src/main/java/org/sxkj/resource/endpoint/OfficeCallbackEndpoint.java b/drone-ops/drone-resource/src/main/java/org/sxkj/resource/endpoint/OfficeCallbackEndpoint.java
index 19d8565..ca9c313 100644
--- a/drone-ops/drone-resource/src/main/java/org/sxkj/resource/endpoint/OfficeCallbackEndpoint.java
+++ b/drone-ops/drone-resource/src/main/java/org/sxkj/resource/endpoint/OfficeCallbackEndpoint.java
@@ -1,6 +1,8 @@
package org.sxkj.resource.endpoint;
import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
@@ -13,15 +15,14 @@
import org.springblade.core.oss.model.BladeFile;
import org.springblade.core.tenant.annotation.NonDS;
import org.springblade.core.tool.utils.FileUtil;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
+import org.sxkj.common.utils.file.FileNameHarsher;
import org.sxkj.resource.builder.OssBuilder;
import org.sxkj.resource.dto.OfficeCallbackDTO;
import org.sxkj.resource.entity.Attach;
import org.sxkj.resource.service.IAttachService;
+import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
@@ -52,58 +53,97 @@
/**
* ONLYOFFICE 保存回调接口
- * 对应前端 config.editorConfig.callbackUrl = "http://localhost:8080/office/callback"
+ * <p>
+ * 处理ONLYOFFICE文档编辑保存回调,支持以下状态:
+ * status=2: 文档编辑完成,关闭编辑器时触发
+ * status=6: 文档强制保存(forcesave)时触发
+ * </p>
+ * <p>
+ * 对应前端 config.editorConfig.callbackUrl = "http://192.168.1.33:8310/office/callback"
+ * </p>
*
- * @param callbackDTO 回调数据对象
- * @return 回调响应结果
+ * @param payload 回调数据对象,包含status、url、key、filetype等字段
+ * @param response HTTP响应对象
+ * @return 回调响应结果,{"error":0}表示成功
*/
@SneakyThrows
@PostMapping("/callback")
@ApiOperation(value = "ONLYOFFICE保存回调", notes = "ONLYOFFICE文档编辑保存回调接口")
- public Map<String, Object> officeCallback(@RequestBody OfficeCallbackDTO callbackDTO) {
- log.info("ONLYOFFICE回调开始,回调数据: {}", JSON.toJSONString(callbackDTO));
- Map<String, Object> result = new HashMap<>(4);
+ public Map<String, Object> officeCallback(@RequestBody JSONObject payload, HttpServletResponse response) {
+ log.info("ONLYOFFICE回调开始,回调数据: {}", JSON.toJSONString(payload));
- // 步骤1:获取回调状态和文件信息
- String status = callbackDTO.getStatus();
- String fileKey = callbackDTO.getKey();
- String fileDownloadUrl = callbackDTO.getUrl();
+ // 1. 获取回调状态码
+ Integer status = payload.getInteger("status");
+ log.info("回调状态status={}", status);
- try {
- // 步骤2:判断是否是保存操作(1=手动保存,2=强制保存)
- if ("1".equals(status) || "2".equals(status)) {
- // 步骤3:下载ONLYOFFICE返回的新文件
- byte[] fileContent = downloadFile(fileDownloadUrl);
-
- // 步骤4:获取文件名(可根据业务需求从数据库获取原始文件名)
- String fileName = generateFileName(fileKey);
-
- // 步骤5:上传文件到OSS
- BladeFile bladeFile = uploadToOss(fileName, fileContent);
- log.info("ONLYOFFICE文件下载成功,文件名: {}, 文件大小: {}", fileName, fileContent.length);
- // 步骤6:保存附件信息到数据库
- Long attachId = saveAttachInfo(fileName, fileContent.length, bladeFile);
-
- // 步骤7:记录操作日志(可根据业务需求扩展)
- log.info("ONLYOFFICE文件保存成功,文件key: {}, 文件名: {}, 附件ID: {}, 下载URL: {}",
- fileKey, fileName, attachId, bladeFile.getLink());
-
- // 步骤8:业务扩展(可根据需求添加)
- // - 更新数据库文件地址、版本号、更新时间
- // - 记录操作日志、操作用户
- // - 发送通知等
- }
-
- // 步骤9:成功必须返回 error:0
- result.put("error", 0);
- } catch (Exception e) {
- // 步骤10:异常处理,非0代表失败,编辑器会提示保存失败
- log.error("ONLYOFFICE文件保存异常,文件key: {}, 异常信息: {}", fileKey, e.getMessage(), e);
- result.put("error", 1);
- result.put("message", "文件保存异常:" + e.getMessage());
+ // 2. 获取编辑后文件下载地址
+ String downloadUrl = payload.getString("url");
+ if (downloadUrl != null) {
+ log.info("编辑后新版文件下载地址: {}", downloadUrl);
}
- return result;
+ // 3. 获取文档唯一标识key
+ String key = payload.getString("key");
+ log.info("回调key={}", key);
+
+ try {
+ // 4. 处理不同状态码
+ // status=2: 文档被关闭,所有用户都退出编辑,需要保存
+ // status=6: 文档强制保存(forcesave),编辑过程中定时或手动触发
+ if ((status == 2 || status == 6) && downloadUrl != null) {
+ handleSaveCallback(payload, key, downloadUrl);
+ }
+
+ // 5. 成功必须返回 {"error":0}
+ return Map.of("error", 0);
+ } catch (Exception e) {
+ log.error("ONLYOFFICE回调处理失败,status={}, key={}, 错误: {}", status, key, e.getMessage(), e);
+ // 异常返回非0,文档服务判定保存失败
+ return Map.of("error", 1);
+ }
+ }
+
+ /**
+ * 处理保存回调(status=2或status=6)
+ * <p>
+ * 从ONLYOFFICE服务器下载编辑后的文件,上传到OSS,
+ * 并更新附件表中的link和md5字段。
+ * </p>
+ *
+ * @param payload 回调数据对象
+ * @param key 文档唯一标识,对应附件表的md5字段
+ * @param downloadUrl 编辑后文件的下载地址
+ * @throws Exception 下载、上传或更新数据库时的异常
+ */
+ private void handleSaveCallback(JSONObject payload, String key, String downloadUrl) throws Exception {
+ // 1. 根据key(md5)查询附件记录
+ Attach attach = attachService.getOne(
+ Wrappers.lambdaQuery(Attach.class).eq(Attach::getMd5, key)
+ );
+ if (attach == null) {
+ log.warn("未找到key={}对应的附件记录,跳过保存", key);
+ return;
+ }
+ log.info("找到附件记录,attachId={}, name={}", attach.getId(), attach.getName());
+
+ // 2. 从ONLYOFFICE服务器下载编辑后的文件
+ log.info("开始从ONLYOFFICE下载编辑后文件: {}", downloadUrl);
+ byte[] fileContent = downloadFile(downloadUrl);
+ log.info("文件下载完成,大小: {} bytes", fileContent.length);
+
+ // 3. 上传文件到OSS
+ String fileName = attach.getName() != null ? attach.getName() : key + ".docx";
+ BladeFile bladeFile = uploadToOss(fileName, fileContent);
+ log.info("文件上传OSS完成,新link: {}", bladeFile.getLink());
+
+ // 4. 更新附件记录的link和md5
+ String newLink = bladeFile.getLink();
+ String newMd5 = FileNameHarsher.generateFileHash(newLink);
+ attach.setLink(newLink);
+ attach.setMd5(newMd5);
+ attach.setAttachSize((long) fileContent.length);
+ attachService.updateById(attach);
+ log.info("附件记录更新完成,attachId={}, 新md5={}", attach.getId(), newMd5);
}
/**
--
Gitblit v1.9.3