找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

295

积分

1

好友

31

主题
发表于 13 小时前 | 查看: 1| 回复: 0

在现代Web应用中,实现在线文档编辑是一个常见的需求。经过调研,我选择了功能强大的开源套件OnlyOffice来满足项目对Word文档的在线编辑与保存需求。OnlyOffice功能丰富,涵盖文档格式转化、多人协同编辑等,本文主要聚焦于其核心的文档编辑功能。

1. OnlyOffice服务部署

部署OnlyOffice主要有两种方式:Docker部署和本地直接安装。相比之下,Docker部署更为简便,只需拉取官方镜像并配置相应参数即可启动。不过,在本次实践中,我选择了在Ubuntu系统上进行本地安装。以下是两种方式的参考文档,本地安装路线已验证可行:

2. 应用代码开发

本项目采用前后端分离架构,前端基于Element UI的Vue框架,后端使用SpringBoot构建。

2.1 前端集成

前端核心是引入OnlyOffice的文档编辑器API。首先,在页面中引入JS脚本,注意将documentserver替换为你部署的OnlyOffice服务地址。

<div id="placeholder"></div>

随后,配置编辑器参数并初始化:

const config = {
    document: {
        mode: 'edit',
        fileType: 'docx',
        key: String(Math.floor(Math.random() * 10000)), // 文档唯一标识
        title: route.query.name + '.docx',
        url: import.meta.env.VITE_APP_API_URL + `/getFile/${route.query.id}`, // 后端获取文件的接口
        permissions: {
            comment: true,
            download: true,
            modifyContentControl: true,
            edit: true,
        },
    },
    documentType: 'word',
    editorConfig: {
        user: { id: 'user1', name: '用户' },
        customization: {
            plugins: false,
            forcesave: true, // 启用强制保存
        },
        lang: 'zh',
        callbackUrl: import.meta.env.VITE_APP_API_URL + `/callback`, // 关键:保存回调地址
    },
    height: '100%',
    width: '100%',
};
new window.DocsAPI.DocEditor('onlyoffice', config);

关键参数说明

  • url:指向后端提供的文件下载接口(如http://your-api:8089/getFile/12)。
  • callbackUrl:文档状态(如编辑、保存、关闭)发生变化时,OnlyOffice服务将向此地址发起POST回调,这是实现文档保存的关键。

2.2 后端开发(SpringBoot)

后端主要提供两个核心接口:getFile(提供文档流)和callback(处理保存回调)。

1. 添加依赖pom.xml中添加HttpClient依赖用于后续文件下载。

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpmime</artifactId>
</dependency>

2. 文件下载接口 (/getFile/{id}) 此接口根据业务ID查询到文档的物理存储路径,并将文件以流的形式返回给前端编辑器。

@GetMapping("/getFile/{meeting_id}")
public ResponseEntity<byte[]> getFile(@PathVariable Long meeting_id) throws IOException {
    // 1. 根据ID从数据库查询会议信息,获取文件存储路径 meetingMinutesFilePath
    MeetingTable meetingTable = meetingTableService.selectMeetingTableById(meeting_id);
    String filePath = meetingTable.getMeetingMinutesFilePath();

    if (filePath == null || filePath.isEmpty()) {
        return null;
    }

    File file = new File(filePath);
    try (FileInputStream fis = new FileInputStream(file);
         BufferedInputStream bis = new BufferedInputStream(fis)) {

        byte[] buffer = new byte[bis.available()];
        bis.read(buffer);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.setContentDispositionFormData("attachment", URLEncoder.encode(file.getName(), "UTF-8"));
        return new ResponseEntity<>(buffer, headers, HttpStatus.OK);
    } catch (Exception e) {
        throw new RuntimeException("文件读取失败", e);
    }
}

3. 回调接口 (/callback) 这是实现文档保存的核心。当用户在编辑器中进行保存操作后,OnlyOffice服务会将最新的文档临时下载地址(url字段)通过此接口通知我们的应用。

@PostMapping("/callback")
public ResponseEntity<Object> handleCallback(@RequestBody CallbackData callbackData) {
    Integer status = callbackData.getStatus();
    switch (status) {
        case 2: // 文档已准备好保存
        case 6: // 正在编辑,但当前文档状态已保存 (定时自动保存)
            System.out.println("准备保存文档...");
            String latestFileUrl = callbackData.getUrl(); // OnlyOffice生成的临时文件地址
            try {
                // 将临时文件下载并覆盖到原始存储路径
                HttpsKitWithProxyAuth.downloadFile(latestFileUrl, meetingMinutesFilePath);
                System.out.println("文档保存成功.");
            } catch (Exception e) {
                System.out.println("保存文件异常: " + e.getMessage());
            }
            break;
        case 3:
            System.out.println("文档保存出错");
            break;
        case 4:
            System.out.println("文档关闭且无修改");
            break;
        // 其他状态码处理...
        default:
            break;
    }
    // 必须返回特定格式的响应
    return ResponseEntity.ok(Collections.singletonMap("error", 0));
}

// 回调数据接收实体类
@Setter
@Getter
public static class CallbackData {
    private String key;
    private Integer status; // 状态码(最重要)
    private String url;     // 待保存的新文件地址(status=2,3,6,7时存在)
    private String lastsave;
    // ... 其他字段根据官方文档定义
}

4. 文件下载工具类 HttpsKitWithProxyAuth.downloadFile(String url, String savePath) 方法是一个通用的HTTP文件下载工具,用于将回调中提供的url文件下载到本地指定路径。其内部基于Apache HttpClient实现,代码较长,核心逻辑是发起GET请求并将响应流写入本地文件。由于篇幅限制,此处不展开,可在文末参考链接中找到实现思路。

3. 常见问题与解决方案

3.1 访问示例页面失败

部署完成后,访问 http://your-doc-server/example 可能失败。首先检查服务是否正常启动:

systemctl status ds*

确保 documentserver, documentserver-example 等相关服务处于 active (running) 状态。

3.2 文档加载或保存失败

大多数权限或连接问题可通过修改OnlyOffice配置文件解决。主要配置文件位于 /etc/onlyoffice/documentserver/ 目录下的 local.jsondefault.json

  • 禁用令牌验证(用于简化调试): 在 local.json 中找到 token 部分,将所有 enable 下的值改为 false
    "token": {
      "enable": {
        "request": { "inbox": false, "outbox": false },
        "browser": false
      }
    }
  • 允许访问内网/元IP地址: 在 default.json 中,确保 request-filtering-agent 配置允许私有IP。
    "request-filtering-agent" : {
      "allowPrivateIPAddress": true,
      "allowMetaIPAddress": true
    }
  • 禁用SSL证书严格验证(仅用于内网测试): 在 default.json 中,将 rejectUnauthorized 设为 false
    "rejectUnauthorized": false

    修改配置后,务必重启OnlyOffice服务:

    sudo systemctl restart ds-example ds-docservice ds-converter

3.3 后端接口身份认证冲突

如果你的SpringBoot应用使用了JWT等全局安全过滤器,需要确保OnlyOffice的回调接口(/callback)和文件下载接口(/getFile/*)被排除在认证之外。在Spring Security配置中将其加入白名单:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        .antMatchers("/callback", "/getFile/**").permitAll() // 放行OnlyOffice相关接口
        .anyRequest().authenticated()
        ... // 其他配置
}

3.4 使用公网文档地址测试

在开发初期,为了快速验证OnlyOffice服务本身是否部署成功,可以绕过自己的后端,直接让前端编辑器加载一个公网的.docx文件地址进行测试。例如:

url: 'https://d2nlctn12v279m.cloudfront.net/assets/docs/samples/zh/demo.docx'

如果此链接能正常打开编辑,说明OnlyOffice服务运行正常,问题可能出在自身后端接口或网络配置上。

4. 总结

整合SpringBoot与OnlyOffice实现在线编辑功能,关键在于理解两者间的交互流程:前端初始化编辑器并配置回调地址 -> 后端提供文件下载接口 -> 用户编辑保存 -> OnlyOffice调用回调接口通知后端 -> 后端从回调提供的地址下载新文件覆盖旧文件。整个过程涉及服务部署、网络配置和安全策略调整,需要耐心调试。本文记录的实施要点和问题解决方案,希望能帮助你在Linux环境下顺利完成集成。

您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区(YunPan.Plus) ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-3 14:20 , Processed in 0.977662 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 CloudStack.

快速回复 返回顶部 返回列表