Springboot集成OnlyOffice

一、OnlyOffice 是什么?为什么选择它?​

ONLYOFFICE 是一款开源免费的全功能办公套件,核心优势在于文档在线编辑、实时协同与灵活集成能力,完美适配企业级私有化部署需求。它支持 Word、Excel、PPT、PDF 等主流格式的查看与编辑,还提供 AI 辅助编辑(文本生成、翻译、语法检查)、跨平台协作(内置聊天、音视频通话)、三级加密(静态 / 传输 / 端到端)等进阶功能,且拥有完善的中文文档和活跃社区。​

相比 OpenOffice、Office Online,OnlyOffice 的核心竞争力体现在:​

  1. 开源可定制:社区版基于 AGPL 3.0 协议,支持二次开发(如突破 20 人协同限制);
  1. 集成友好:提供全面的 REST API,支持与 40+ 平台无缝对接(Nextcloud、Moodle 等);
  1. 协同高效:支持字符级实时协作,多人编辑无冲突,自带修订记录与评论功能;
  1. 生态完善:覆盖桌面端(Windows/Linux/macOS)、移动端(iOS/Android)与网页端,满足全场景需求。

适合场景:企业内部文档协作平台、SaaS 产品嵌入在线编辑功能、私有化办公系统搭建等。​

二、Docker 快速部署 OnlyOffice Docs 服务​

Docker 是部署 OnlyOffice 最便捷的方式,无需复杂依赖配置,一键启动完整服务(含文档服务器、数据库)。​

前提条件​

  • 已安装 Docker 与 Docker Compose(推荐 Docker 版本 ≥ 20.10);
  • 服务器内存 ≥ 2GB(官方建议,否则编辑时可能卡顿);
  • 开放 80 端口(或自定义端口),确保网络可访问。

部署步骤​

  1. 拉取官方镜像​

OnlyOffice 文档服务器的官方镜像已包含核心依赖,直接拉取即可:​

拉取最新版 OnlyOffice Docs 镜像​

docker pull onlyoffice/documentserver​

注意:若 Docker Hub 访问受限,可通过国内镜像源同步(如阿里云镜像仓库),避免自行打包镜像(易出现兼容性问题)。​

简化版(无需 MySQL,使用内置 SQLite):​

docker run --name onlyoffice-docs -d -p 8088:80 --restart=always onlyoffice/documentserver​

适合测试环境,生产环境建议用 MySQL 保证数据可靠性。​

onlyoffice默认开启token,如果不需要token可以加-e JWT_ENABLED=false

  1. 验证部署成功​

容器启动后(约 1-2 分钟),访问 http://服务器IP:8088,若看到 OnlyOffice 欢迎页面,则部署成功:​

常见问题解决​

  1. 权限不足:若容器启动失败,添加 --privileged=true 参数赋予权限;
  1. 端口占用:修改 -p 映射端口(如 8089:80),避免与其他服务冲突;
  1. 中文字体缺失:进入容器复制本地中文字体(如 SimHei.ttf)到 /var/www/onlyoffice/documentserver/core-fonts,执行 documentserver-generate-allfonts.sh 刷新缓存。

SpringBoot的集成

在动手写代码前,我们需要先理清集成的核心逻辑,准备好所需环境,避免后续踩坑。

核心原理:OnlyOffice 与 Spring Boot 如何交互?

OnlyOffice 的集成本质是 "前端渲染 + 后端通信" 的组合:

  • 前端:通过 OnlyOffice 提供的 JavaScript API,在页面中嵌入文档编辑器组件,负责文档的可视化编辑、格式渲染;
  • 后端(Spring Boot) :作为 "中间桥梁",承担三个关键角色:
    1. 提供文档文件的存储(本地 / 云存储)与访问接口(如下载文档的 URL);
    2. 处理 OnlyOffice 的回调通知(如文档编辑完成后,接收 OnlyOffice 返回的编辑结果,更新本地文件)。

简单来说:用户在前端编辑文档时,操作会实时同步到 OnlyOffice 服务端;编辑完成后,OnlyOffice 会通知 Spring Boot 后端,后端再从 OnlyOffice 获取最新文档并保存 ------ 整个流程需保证 "文件地址可访问""接口权限合法""回调处理可靠"。

步骤 1:配置 OnlyOffice 服务地址

application.properties 中配置 OnlyOffice 服务地址和回调接口地址:

复制代码
# OnlyOffice Document Server 地址(前端加载编辑器用)
onlyoffice.server.url=http://onlyoffice-ip:8080
# 后端回调接口地址(OnlyOffice 保存文档时调用)
onlyoffice.callback.url=http://your-springboot-ip:8081/api/onlyoffice/callback
# 文档存储路径(本地存储示例)
doc.storage.path=/app/documents/

步骤 2:后端核心接口实现

2.1 文档配置接口(给前端返回编辑器参数)

前端加载 OnlyOffice 编辑器时,需要从后端获取文档的配置信息(如文件地址、权限、回调地址等)。

java 复制代码
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/api/onlyoffice")
public class OnlyOfficeController {

    @Value("${onlyoffice.server.url}")
    private String onlyofficeServerUrl;

    @Value("${onlyoffice.callback.url}")
    private String callbackUrl;

    @Value("${doc.storage.path}")
    private String docStoragePath;

    // 文档配置接口:前端请求此接口获取编辑器参数
    @GetMapping("/config")
    public Map<String, Object> getDocConfig(@RequestParam String fileName) throws Exception {
        // 1. 构建文档访问地址(后端提供的文档下载地址)
        String docUrl = "http://your-springboot-ip:8081/api/doc/download?fileName=" + fileName;

        // 2. 配置 OnlyOffice 编辑器参数
        Map<String, Object> config = new HashMap<>();
        config.put("document", Map.of(
                "fileType", fileName.split("\\.")[1], // 文档类型(如 docx、xlsx)
                "key", fileName, // 文档唯一标识(建议用文件MD5或UUID)
                "title", fileName,
                "url", docUrl // 文档下载地址(OnlyOffice 会从这里拉取文件)
        ));

        // 3. 配置编辑器权限(是否可编辑)
        config.put("editorConfig", Map.of(
                "callbackUrl", callbackUrl, // 保存回调地址
                "user", Map.of("id", "1", "name", "张三"), // 当前用户信息
                "mode", "edit" // 模式:edit(编辑)/ view(查看)
        ));

        // 4. 配置 OnlyOffice 服务地址
        config.put("documentServerUrl", onlyofficeServerUrl);

        return config;
    }
}
2.2 文档下载接口(OnlyOffice 拉取文件用)

OnlyOffice 编辑器需要从后端下载文档进行编辑,因此需要提供一个下载接口:

java 复制代码
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.io.File;

@RestController
@RequestMapping("/api/doc")
public class DocController {

    @Value("${doc.storage.path}")
    private String docStoragePath;

    // 文档下载接口:OnlyOffice 从这里拉取文件
    @GetMapping("/download")
    public ResponseEntity<byte[]> downloadDoc(@RequestParam String fileName) throws Exception {
        File docFile = new File(docStoragePath + fileName);
        if (!docFile.exists()) {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }

        // 设置响应头(指定文件类型)
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.setContentDispositionFormData("attachment", fileName);

        return new ResponseEntity<>(FileUtils.readFileToByteArray(docFile), headers, HttpStatus.OK);
    }
}
2.3 回调接口(OnlyOffice 保存文档时调用)

当用户编辑完成并点击保存后,OnlyOffice 会将编辑后的文档通过回调接口发送到后端,后端需要接收并保存文件。

java 复制代码
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.io.File;
import java.net.URL;

@RestController
@RequestMapping("/api/onlyoffice")
public class OnlyOfficeCallbackController {

    @Value("${doc.storage.path}")
    private String docStoragePath;

    private final ObjectMapper objectMapper = new ObjectMapper();

    // 回调接口:OnlyOffice 保存文档时调用
    @PostMapping("/callback")
    public ResponseEntity<String> callback(@RequestBody JsonNode body) throws Exception {
        // 1. 解析回调参数
        String status = body.get("status").asText(); // 状态:2 - 已保存,3 - 保存并关闭
        if (!"2".equals(status) && !"3".equals(status)) return ResponseEntity.ok("{\"error\":0}");
        String url = body.get("url").asText(); // 编辑后文档的临时URL(OnlyOffice 提供)
        String fileName = body.get("key").asText(); // 文档唯一标识(与配置中的key一致)

        // 2. 状态为2或3时,下载并保存文档
        if ("2".equals(status) || "3".equals(status)) {
            // 从 OnlyOffice 提供的临时URL下载编辑后的文件
            File editedFile = new File(docStoragePath + fileName);
            FileUtils.copyURLToFile(new URL(url), editedFile);
        }

        // 3. 必须返回 {"error":0},否则 OnlyOffice 会认为回调失败并重复调用
        return ResponseEntity.ok("{\"error\":0}");
    }
}

步骤 3:前端页面集成 OnlyOffice 编辑器

前端需要引入 OnlyOffice 的 JS 脚本,并通过后端返回的配置信息初始化编辑器。

示例(HTML + JavaScript):

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>OnlyOffice 编辑示例</title>
    <!-- 引入 OnlyOffice 编辑器脚本(地址为部署的 Document Server) -->
    <script src="http://onlyoffice-ip:8080/web-apps/apps/api/documents/api.js"></script>
</head>
<body>
    <!-- 编辑器容器 -->
    <div id="onlyofficeEditor" style="width: 100%; height: 800px;"></div>

    <script>
        // 从后端获取文档配置
        fetch('http://your-springboot-ip:8081/api/onlyoffice/config?fileName=test.docx')
            .then(response => response.json())
            .then(config => {
                // 初始化 OnlyOffice 编辑器
                new DocsAPI.DocEditor("onlyofficeEditor", config);
            });
    </script>
</body>
</html>
相关推荐
葫芦和十三12 小时前
图解 MongoDB 22|读写关注:持久性与一致性的档位选择
后端·mongodb·agent
葫芦和十三18 小时前
图解 MongoDB 21|选举与 failover:Primary 是怎么选出来的
后端·mongodb·agent
GetcharZp19 小时前
26k Star 开源内网穿透神器 NetBird,一分钟实现全球设备互联!
后端
考虑考虑19 小时前
Mybatis实现批量插入
java·后端·mybatis
咖啡八杯20 小时前
GoF设计模式——中介者模式
java·后端·spring·设计模式
lizhongxuan1 天前
多Agent之间的区别
后端
青石路1 天前
记一次多JDK版本问题的排查,一坑套一坑,差点没爬上来
java
杨充1 天前
1.面向对象设计思想
后端
IT_陈寒1 天前
Java的Date类又坑了我一次,改用时间戳真香
前端·人工智能·后端
systemPro1 天前
2.6亿条设备数据,历史查询从超时到50ms,我做了什么
后端