SpringBoot实战(二十八)集成 Collabora Online 实现在线编辑

news2024/12/24 0:22:09

目录

    • 一、什么是 Collabora Online?
    • 二、Docker 下载并启动 CODE
      • 2.1 拉取镜像
      • 2.2 启动镜像
      • 2.3 访问界面
      • 2.4 补充:nextcloud 的镜像启动
    • 三、SpringBoot 实现 WOPI 服务
      • 3.1 什么是WOPI?
      • 3.2 Spring Boot 简单实现
      • 3.3 另一种实现方式
      • 3.4 总结
    • 四、补充:coolwsd.xml 核心配置介绍
      • coolwsd.xml 核心配置1:<alias_groups>
      • coolwsd.xml 核心配置2:\<ssl\>
      • coolwsd.xml 核心配置3:\<frame_ancestors>
      • coolwsd.xml 核心配置4:\<service_root>
    • 五、踩坑记录
      • 5.1 nginx配置踩坑

  • Collabora Online 官网地址: https://www.collaboraoffice.com/
  • SDK官网地址: https://sdk.collaboraonline.com/
  • 官方文档: https://sdk.collaboraonline.com/
  • GitHub: https://github.com/CollaboraOnline/online
  • WOPI 官方文档: https://api.onlyoffice.com/zh/editors/wopi/discovery
  • 官方 nodejs demo: https://github.com/CollaboraOnline/collabora-online-sdk-examples//tree/master/webapp/nodejs

一、什么是 Collabora Online?

Collabora Onlnien 是一款 开源的 基于 LibreOffice 的云办公套件,它允许用户在浏览器中 创建、编辑和协作处理文档、电子表格、演示文稿和绘图。它是由 Collabora Productivity Ltd 开发的,这家公司是 LibreOffice 社区的主要贡献者之一。

页面如下所示:

在这里插入图片描述

点进 Collabora Online 的主页我们可以看到,它的核心产品主要包含如下三类:

  • Collabora Online: 是一款基于 Web 的在线办公套件,用户可以通过浏览器访问和使用,不需要在本地计算机上安装任何软件。
  • Collabora Office: 是一款桌面版的办公套件,可在 Windows、macOS 和 Linux 上本地安装。
  • Collabora Online Development Edition: 缩写为 CODE,直译过来就是 Collabora Online 的 开发版,可以在项目中集成后使用。

这里我们主要使用的就是其中的开发版的 CODE。在 CODE 中已经实现了很多的成熟的集成方式:

  • Alfresco integration:(Java集成)
    git clone https://github.com/CollaboraOnline/alfresco-collabora-online.git
  • EGroupware integration:
    git clone https://github.com/EGroupware/collabora.git
  • Mattermost integration:
    git clone https://github.com/CollaboraOnline/collabora-mattermost.git
  • Collaborative document editing:
    git clone https://github.com/learnweb/moodle-mod_collabora.git
  • Collaborative submissions:
    git clone https://github.com/CollaboraOnline/collabora-mattermost.git
  • Nextcloud integration:(PHP集成)
    git clone https://github.com/CollaboraOnline/richdocumentscode.git
  • ownCloud integration:(PHP集成)
    git clone https://github.com/CollaboraOnline/richdocumentscode-owncloud.git

(参考:https://sdk.collaboraonline.com/docs/available_integrations.html)

下面是我们使用 SpringBoot 集成 Collabora Online 后的请求过程:

在这里插入图片描述

下面我们就来说一下如何下载并启动 CODE 镜像以及如何使用 SpringBoot 集成后实现文件的在线编辑和预览。


二、Docker 下载并启动 CODE

2.1 拉取镜像

  • 官方的镜像地址: https://hub.docker.com/r/collabora/code/

首先,使用如下命令拉取镜像:

docker pull collabora/code:latest

拉取过程如下,速度会有些慢:

在这里插入图片描述

可以使用阿里的镜像源,加快拉取速度:

{
   
 "registry-mirrors":["https://6kx4zyno.mirror.aliyuncs.com"]
}

拉取完毕之后,镜像如下所示:

在这里插入图片描述

2.2 启动镜像

镜像拉取完毕之后,使用如下命令启动镜像即可:

docker run \
--name "collabora_code" \
-t \
-d \
-p 0.0.0.0:9980:9980 \
-e "username=admin" \
-e "password=Pwd4C0De" \
--cap-add MKNOD \
--privileged \
-v /etc/collabora/coolwsd.xml:/etc/coolwsd/coolwsd.xml \
collabora/code:latest

补充:--privileged 是让当前容器的用户即使不是 root,也可以执行任何需要root权限的操作。

coolwsd.xml 是 Collabora Online 的配置文件,它控制着 Collabora Online 服务中 是否启用 TSL/SSL 加密字体资源位置对特定 IP 或域名的访问控制 等各种参数的设置。

  • coolwsd:Collabora Online Web Service Daemon 的缩写,它是一个守护进程,运行在服务器上,是 Collabora Online 办公套件的核心组件之一。coolwsd 主要负责提供后台服务,是的用户能够 通过 Web 浏览器访问和使用 LibreOffice 功能,从而实现在线文档编辑和写作。

CODE 镜像 docker run 常用挂载项:

  • 指定 coolwsd.xml 配置文件,里面包含了 CODE 的最最核心配置:

    -v /yourPath/coolwsd.xml:/etc/coolwsd/coolwsd.xml

  • 指定标签页上面的icon图标:

    -v /yourPath/favicon.ico:/usr/share/coolwsd/favicon.ico

  • 指定页面内的系统logo图案:

    -v /yourPath/toolbar-bg-logo.svg:/usr/share/coolwsd/browser/dist/images/toolbar-bg-logo.svg

  • 指定页面内可供使用的字体:(Windows字体可以去 C:\Windows\Fonts\ 路径下找)

    -v /yourPath/winFonts:/opt/cool/systemplate/usr/share/fonts/truetype \

    -v /yourPath/winFonts:/usr/share/fonts/truetype \
    -v /yourPath/winFonts:/opt/collaboraoffice/share/fonts/truetype

  • 指定页面上工具栏哪些可以显示:

    -v /yourPath/bundle.js:/usr/share/coolwsd/browser/dist/bundle.js

2.3 访问界面

  • 在线编辑地址: http://localhost:9980/browser/5303504/cool.html?WOPISrc=http%3A%2F%2F192.168.1.195%3A8080%2Fwopi%2Ffiles%2F92&lang=zh-CN&access_token=123

注意:

  1. 在线编辑地址后面的 WOPISrc 要拼接 WOPI 服务地址的,所以目前还不能访问。可以先访问下管理系统地址。
  2. 通过cool.html访问时,后面传输的任何参数,例如 access_token 都会被转发到对应的 WOPI 服务的请求上,用于鉴权等操作。
  • 管理界面地址: http://localhost:9980/browser/dist/admin/admin.html

访问地址后,界面如下所示:

在这里插入图片描述

2.4 补充:nextcloud 的镜像启动

nextcloud 使用了 PHP 语言集成了 Collabora Online 的一套成熟的系统。

  • 官网地址: https://nextcloud.com/

首先使用如下命令拉取镜像:

docker pull nextcloud:latest

使用如下命令启动镜像:

docker run \
--name nextcloud_test \
-d \
--restart=always \
-p 8880:80 \
  • 访问地址: http://localhost:8880/
  • 账号/密码: admin/Pwd4C0De(由 CODE 启动时指定)

三、SpringBoot 实现 WOPI 服务

3.1 什么是WOPI?

WOPI:全称为 Web Office Protocol Interface,是一种由微软提出的协议,旨在允许 Web 应用程序能够无缝地与 Office 文档进行交互。WOPI 主要应用于在线编辑和预览 Microsoft Office 文档的场景,使得用户可以在 Web应用中直接打开、编辑和保存 Office 文档,而无需下载文档到本地或安装 Office 套件。

  • 官方文档: https://api.onlyoffice.com/zh/editors/wopi/discovery

其实 WOPI 协议就是一系列规定了接口地址、入参/出参的 RESTful 接口规范。核心的接口主要有3个:

  1. 获取文件信息接口:/wopi/file/{id},Get请求

    这个接口可以 获取文件的名称、大小、是否可编辑等信息

    (参考:https://api.onlyoffice.com/zh/editors/wopi/restapi/checkfileinfo)

  2. 获取文件内容接口:/files/{id}/contents,GET请求

    这个接口可以 读取文件的信息,以字节流的形式返回

    (参考:https://api.onlyoffice.com/zh/editors/wopi/restapi/getfile)

  3. 写入文件内容接口:/files/{id}/contents,POST请求

    这个接口用于 写入文件内容,即保存编辑后的内容,将文件流写入文件。

    (参考:https://api.onlyoffice.com/zh/editors/wopi/restapi/putfile)

3.2 Spring Boot 简单实现

WopiController.java

(接口类,用于校验权限、操作文件)

import com.demo.common.model.auth.details.LoginUserUtil;
import com.demo.common.web.Result;
import com.demo.online.vo.WopiFileInfoVO;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Objects;

/**
 * <p> @Title WopiController
 * <p> @Description WOPI在线编辑Controller
 *
 * @author ACGkaka
 */
@Slf4j
@RestController
@RequestMapping("/wopi")
public class WopiController {
   

    @Resource
    private FileInfoService fileInfoService;

    @ApiOperation("在线编辑-根据ID查询文件信息")
    @GetMapping("/files/{id}")
    public WopiFileInfoVO findWopiFileInfoById(@PathVariable("id") String id) {
   
        // 查询信息
        FileInfo file = fileInfoService.getAndCheckPermissionById(id);
        Integer fileSize = file.getSize();
        // 记录日志
        LoginUser loginUser = LoginUserUtil.getLoginUser();
        log.info(">>>>>>>>>>【INFO】WOPI文件信息,uid:{},userName:{},eid:{},orgName:{},fileInfoId:{},fileInfoName:{},editFlag:{}",
                loginUser.getId(), loginUser.getUsername(), loginUser.getEid(), loginUser.getOrgName(), id, fileInfo.getFileInfoName(), fileInfo.getEditFlag());
        // 封装返回
        return new WopiFileInfoVO(fileInfo.getFileInfoName(), fileSize, Objects.equals(fileInfo.getEditFlag(), "1"));
    }

    @ApiOperation("在线编辑-根据ID查询文件内容")
    @GetMapping("/files/{id}/contents")
    public byte[] findWopiFileContentsById(@PathVariable("id") String id) {
   
        fileInfo file = fileInfoService.getAndCheckPermissionById(id);
        return fileInfoService.getBytes(file.getId());
    }

    @ApiOperation("在线编辑-根据ID查询文件内容")
    @PostMapping("/files/{id}/contents")
    public Result<Object> saveWopiFileContentsById(@PathVariable("id") String id, HttpServletRequest request) {
   
        fileInfo fileInfo = fileInfoService.getAndCheckPermissionById(id);
        if (!Objects.equals(fileInfo.getEditFlag(), "1")) {
   
            LoginUser loginUser = SysUserUtil.getloginUser();
            log.error(">>>>>>>>>>【ERROR】暂无权限在线编辑该文件,请确认后重试,fileInfo.getEditFlag():{},fileInfo.getId():{},uid:{}",
                    fileInfo.getEditFlag(), fileInfo.getId(), loginUser.getId());
            throw new IllegalArgumentException("暂无权限在线编辑该文件,请确认后重试");
        }
        FileInfo fileInfo = fileInfoService.getFileInfo(fileInfo.getFileInfoId());
        if (fileInfo == null) {
   
            log.error(">>>>>>>>>>【ERROR】在线文件信息未找到,请刷新后重试,fileInfoId:{}", fileInfo.getFileInfoId());
            throw new IllegalArgumentException("在线文件信息未找到,请刷新后重试");
        }
        writeToFile(Paths.get(fileInfo.getCatalogue() + fileInfo.getPath()), request);
        return Result.succeed();
    }

    /**
     * 将 request 内容写入文件
     */
    private void writeToFile(java.nio.file.Path path, HttpServletRequest request) {
   
        ServletInputStream inputstream;
        try {
   
            inputstream = request.getInputStream();
            java.nio.file.Files.copy(inputstream, path, StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
   
            log.error(">>>>>>>>>>【ERROR】在线文件写入失败,请刷新后重试,原因:{}", e.getMessage(), e);
            throw new IllegalArgumentException("在线文件写入失败,请刷新后重试");
        }
    }
}

WopiFileInfoVO.java

(实体类,用于封装文件信息)

import com.demo.common.model.auth.details.LoginUserUtil;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * <p> @Title WopiFilesByIdVO
 * <p> @Description 文件信息封装(参考文档:https://api.onlyoffice.com/zh/editors/wopi/restapi/checkfileinfo)
 *
 * @author ACGkaka
 * @date 2024/5/28 19:34
 */
@Slf4j
@Data
@NoArgsConstructor
@AllArgsConstructor
public class WopiFileInfoVO {
   

    /**
     * 文件名称(例:test.docx)
     */
    @JsonProperty("BaseFileName")
    private String BaseFileName;
    /**
     * 版本(每次编辑和保存文档时,都必须更改版本。 给定文件的版本号不得重复。例:Khirz6zTPdfd7)
     */
    @JsonProperty("Version")
    private String Version = "Version";
    /**
     * 面包屑导航——客户端向用户显示的名称,用于指示 WOPI 服务器的品牌名称。
     */
    @JsonProperty("BreadcrumbBrandName")
    private String BreadcrumbBrandName = "5G随e签";
    /**
     * 面包屑导航——当用户单击显示 BreadcrumbBrandName的 UI 时,WOPI 客户端导航到的网页的 URL。
     */
    @JsonProperty("BreadcrumbBrandUrl")
    private String BreadcrumbBrandUrl = "https://esign.it.10086.cn/saas/#/login";
//    /**
//     * 面包屑导航——WOPI 客户端向用户显示的文件名。如果未指定此参数,则使用 BaseFileName 参数。
//     */
//    @JsonProperty("BreadcrumbDocName")

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1888257.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

类型“{}”上不存在属性“xxxx”。ts(2339)

解决&#xff1a;类型“{}”上不存在属性“xxxx”和非类型化函数调用不能接受类型参数等问题。 问题发现 今天一个学生&#xff0c;发我一张图&#xff08;如下&#xff09;。 他从远端拉取到本地&#xff08;自家电脑&#xff09;后打开的代码视图&#xff0c;一大堆抛红。问…

s5.日志服务

日志服务 1. rsyslog 系统日志服务2.常见日志文件3. 启用网络日志服务4. 利用 MySQL 存储日志信息5. 日志管理工具 journalctl6. Logrotate 日志转储 1. rsyslog 系统日志服务 rsyslog是CentOS 6 以后版本的系统管理服务.它提供了高性能&#xff0c;出色的安全性和模块化设计。…

vue为啥监听不了@scroll

哈喽 大家好 我在vue中写了一个滚动scroll监听事件 然后滚动鼠标 发现进不来我的方法断点 原因&#xff1a; 事件绑定错误&#xff1a;确保你使用scroll正确绑定到了可滚动容器上。 事件冒泡&#xff1a;滚动事件可能被封装在某些组件内部&#xff0c;导致不会冒泡到父元素上…

背景图的动效,非常的炫酷,非一般的感觉。

我们都知道在一些展示型项目中&#xff0c;背景图加上动效后&#xff0c;可以立马让整个设计档次提升了&#xff0c;这次带来了一批背景图的动效图&#xff0c;大家看一下。

Web 基础与 HTTP 协议

Web 基础与 HTTP 协议 一、Web 基础1.1域名和 DNS域名的概念Hosts 文件DNS&#xff08;Domain Name System 域名系统&#xff09;域名注册 1.2网页与 HTML网页概述HTML 概述网站和主页Web1.0 与 Web2.0 1.3静态网页与动态网页静态网页动态网页 二、HTTP 协议1.1HTTP 协议概述1.…

3115.力扣每日一题7/2 Java

博客主页&#xff1a;音符犹如代码系列专栏&#xff1a;算法练习关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 目录 思路 解题方法 时间复杂度 空间复杂度 Code 总结 思路 这道题的…

SpringBoot+mail 轻松实现各类邮件自动推送

一、简介 在实际的项目开发过程中&#xff0c;经常需要用到邮件通知功能。例如&#xff0c;通过邮箱注册&#xff0c;邮箱找回密码&#xff0c;邮箱推送报表等等&#xff0c;实际的应用场景非常的多。 早期的时候&#xff0c;为了能实现邮件的自动发送功能&#xff0c;通常会…

android iconfont带图标的图文并茂的一种实现

android实现图文并茂方法很多。 这里针对&#xff0c;仅本地图标&#xff0c;需要对齐&#xff0c;任意位置&#xff0c;兼容换行导致后面空白的问题做的一种方案。 www.iconfont.cn&#xff0c;注册&#xff1b; 上传svg的icon&#xff1b; 下载项目得到iconfont.ttf&#xf…

泰雷茲具有首个通过FIPS 140-3 三级认证的HSMs

泰雷兹LunaHsm是业界首款通过FIPS140-33级认证的解决方案&#xff0c;安策引进泰雷兹HSM产品可以帮助您满足您的数据安全合规性需求&#xff0c;阻力企业提高竞争力。 安策提供泰雷茲ThalesLunaHSMs成为首个通过FIPS140-3三级认证的硬件安全模块图 我们很高兴地宣布&#xff0c…

Java 汉诺塔问题 详细分析

汉诺塔 汉诺塔&#xff08;Tower of Hanoi&#xff09;&#xff0c;又称河内塔&#xff0c;是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子&#xff0c;在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小…

Ignis 应用: 社交 + 游戏 + 工业4.0,Ignis 构建Web3生态圈

引言 在数字经济快速发展的今天&#xff0c;Web3技术为我们带来了前所未有的变革。作为Ardor平台的主要子链&#xff0c;Ignis公链在推动Web3生态系统建设中扮演了重要角色。本文将通过介绍Vessel Chain、Mythical Beings和Bridge Champ等应用&#xff0c;探讨Ignis公链如何通…

Android原生与flutter模块交互

Flutter定义了三种不同类型的Channel&#xff1a; BasicMessageChannel&#xff1a;用于传递字符串和半结构化的信息&#xff0c;持续通信&#xff0c;收到消息后可以回复此次消息&#xff0c;如&#xff1a;Native将遍历到的文件信息陆续传递到Dart&#xff0c;在比如&#xf…

【Python机器学习系列】建立决策树模型预测小麦品种(案例+源码)

这是我的第314篇原创文章。 一、引言 对于表格数据&#xff0c;一套完整的机器学习建模流程如下&#xff1a; 针对不同的数据集&#xff0c;有些步骤不适用&#xff0c;其中橘红色框为必要步骤&#xff0c;欢迎大家关注翻看我之前的一些相关文章。前面我介绍了机器学习模型的二…

MySQL 9.0 发布了!

从昨晚开始&#xff0c;在DBA群里大家就在讨论MySQL 9.0发布的事情&#xff0c;但是Release Note和官方文档都没有更新&#xff0c;所以今天早上一上班就赶紧瞅了下具体更新了哪些内容&#xff1f; 整体看来&#xff0c;基本没什么创新。下面是9.0新增或废弃的一些特性。 &…

自动批量将阿里云盘文件发布成WordPress文章脚本源码(以RiPro主题为例含付费信息下载地址SEO等自动设置)源码

背景 很多资源下载站&#xff0c;付费资源下载站&#xff0c;付费内容查看等都可以用WordPress站点发布内容&#xff0c;这些站点一般会基于一个主题&#xff0c;付费信息作为文章附属的信息发布&#xff0c;底层存储在WP表里&#xff0c;比如日主题&#xff0c;子比主题等。 …

计算机是如何看到图像的

本节课为「计算机视觉 CV 核心知识」第 4 节&#xff1b; 「AI秘籍」系列课程&#xff1a; 人工智能应用数学基础人工智能Python基础人工智能基础核心知识人工智能BI核心知识人工智能CV核心知识 本文涉及代码&#xff1a;https://github.com/hivandu/AI_Cheats Hi, 大家好。我…

【MySQL备份】Percona XtraBackup压缩备份实战篇

目录 1.前言 2.准备工作 2.1.环境信息 2.2.配置/etc/my.cnf文件 2.3.授予root用户BACKUP_ADMIN权限 2.4.安装qpress 3. 压缩备份 3.1.创建压缩备份 3.2.创建全量备份 3.3.对比两个备份的大小 4.解压备份 5.准备备份 6.备份恢复 ​7.问题分析 8.总结 "实战…

网络连接之队头阻塞!!!

一、什么是队头阻塞 队头阻塞&#xff0c;在网络模型中简单理解就是&#xff0c;对于队列型的请求模型&#xff0c;如HTTP的请求-响应模型、TCP的ACK确认机制&#xff0c;都依赖得到一个具体的响应包&#xff0c;如果收不到这个响应包&#xff0c;那下一个请求就不能发&#x…

太阳辐射系统日光全光谱模拟太阳光模拟器

太阳光模拟器是一种用于评估太阳能电池性能的重要设备。它能够模拟太阳光的特性&#xff0c;通过测试电池的短路电流、开路电压、填充因子和光电转化效率等关键指标&#xff0c;来评估电池的性能优劣。 设备型号&#xff1a;KYF-GC004品牌制造商&#xff1a;科迎法电气太阳光模…

08 docker Registry搭建docker私仓

目录 本地镜像发布流程 1. docker pull registry 下载镜像 2. docker run 运行私有库registry 3. docker commit 构建镜像 4. docker tag 修改新镜像&#xff0c;使之符合私服规范tag 5. 修改配置文件使之支持http 6. curl验证私服库上有什么镜像 7. push推送 pull拉取 …