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

目录

    • 一、什么是 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 {@Resourceprivate 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.mzph.cn/pingmian/40409.shtml

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

相关文章

LeetCode 1327, 383, 236

目录 1327. 列出指定时间段内所有的下单产品题目链接表要求知识点思路代码 383. 赎金信题目链接标签思路代码 236. 二叉树的最近公共祖先题目链接标签思路代码 1327. 列出指定时间段内所有的下单产品 题目链接 1327. 列出指定时间段内所有的下单产品 表 表Products的字段为…

matlab 干涉图仿真

目录 一、算法概述1、干涉图2、生成步骤 二、代码实现三、结果展示 本文由CSDN点云侠原创&#xff0c;原文链接。如果你不是在点云侠的博客中看到该文章&#xff0c;那么此处便是不要脸的爬虫。 一、算法概述 1、干涉图 干涉图是两束或多束相干光波相遇时&#xff0c;它们的振…

【软件测试】Selenium自动化测试框架 | 相关介绍 | Selenium + Java环境搭建 | 常用API的使用

文章目录 自动化测试一、selenium1.相关介绍1.Selenium IDE2.Webdriverwebdriver的工作原理&#xff1a; 3.selenium Grid 2.Selenium Java环境搭建3.常用API的使用1.定位元素2.操作测试对象3.添加等待4.打印信息5.浏览器的操作6.键盘事件7.鼠标事件8.定位一组元素9.多层框架定…

[笔记] 卷积03 - 运算的对称性 时域构建高通滤波器的失败尝试

1.卷积运算具备足够好的对称性 1.在计算卷积时&#xff0c;两个函数的位置是可以颠倒的&#xff0c;对吧&#xff1f; 在卷积运算中&#xff0c;确实可以对参与卷积的两个函数进行颠倒。这是因为卷积的定义是通过一个函数与另一个函数的翻转后的形式进行积分运算。具体来说&a…

DPDK概述

文章目录 1. DPDK概述1.1 DPDK 内存管理Mbuf单帧结构:1.2 DPDK内核驱动 igb_uio驱动1.3 DPDK源码下载方式1.4 pktgen源码下载方式1.5 DPDK相关名词解释 1. DPDK概述 Intel DPDK全称Intel Data Plane Development Kit&#xff0c;是Intel提供的数据平面开发工具集&#xff0c;为…

第十三章 Nest Middleware

在上一章我们了解到Nest 并不直接依赖Express 可以切换到别的http 请求处理库 创建项目&#xff1a; nest new middleware-test -p npm创建 middleware &#xff1a; nest g middleware test --no-spec --flat这时候可以看到 req 和 res 的类型都是为 any类型 所以并不知道使…

算法力扣刷题记录 二十八【225. 用队列实现栈】

前言 栈和队列篇。 记录 二十八【225. 用队列实现栈】 一、题目阅读 请你仅使用两个队列实现一个后入先出&#xff08;LIFO&#xff09;的栈&#xff0c;并支持普通栈的全部四种操作&#xff08;push、top、pop 和 empty&#xff09;。 实现 MyStack 类&#xff1a; void p…

实验四 SQL的数据定义语句

题目 通过SQL语句创建名为ecommerce1的数据库&#xff1a;CREATE DATABASE ecommerce1 2、在数据库ecommerce1中练习模式的创建和删除语句&#xff08;如给用户li创建一个学生管理模式“S-T”&#xff09;&#xff08;需要先添加一个用户li&#xff09; 3、在数据库ecommerce1中…

7月4号直播预告 | 全国产EtherCAT运动控制器ZMC432HG及其EtherCAT总线使用

EtherCAT运动控制边缘控制器是工业互联网的关键组件之一&#xff0c;结合丰富的运动控制功能、实时数据采集、处理和本地计算等&#xff0c;具备高度灵活的可编程性和出色的运动控制性能&#xff0c;为运动控制协同工业互联网应用带来巨大市场潜力&#xff0c;同时也使其成为企…

ID3算法决策树

步骤&#xff1a; 先计算出信息量&#xff1b;信息熵&#xff1b;信息增量&#xff1b; 再比较信息增量的大小&#xff0c;确定分类依据。 信息量&#xff1a; 信息熵&#xff1a; 信息增益&#xff1a;

Postman使用教程

传统接口风格 RESTful风格 使用Postman完成测试用例目标&#xff1a; Postman教程 &#xff08;1&#xff09;准备工作&#xff0c;下载Postman新建 &#xff08;2&#xff09;登录接口调试-获取验证码 &#xff08;3&#xff09;登录接口调试-登录 &#xff08;4&#xff09;…

Mysql查询IFNULL和想象的不一样

select sum(ifnull(a,0)) aaa,ifnull(sum(a),0) bbb from (select g.goodsid a from goods g where g.goodsid 601 ) tmp #注意 goodsid 601 的不存在 ​​​ 返回的结果和想象中不同&#xff0c;解释如下 在您SQL查询中&#xff0c;创建了一个子查询&#xff08;别名为tmp&a…

Linux_管道通信

目录 一、匿名管道 1、介绍进程间通信 2、理解管道 3、管道通信 4、用户角度看匿名管道 5、内核角度看匿名管道 6、代码实现匿名管道 6.1 创建子进程 6.2 实现通信 7、匿名管道阻塞情况 8、匿名管道的读写原子性 二、命名管道 1、命名管道 1.1 命名管道通信 …

国内外大模型集合

为了满足日益增长的AI需求&#xff0c;我们精心打造了一站式大模型导航网站&#xff0c;旨在成为连接您与全球顶尖人工智能模型的桥梁。无论您是科研工作者、开发者还是对AI充满好奇的探索者&#xff0c;这里都有您所需。 国内大模型精选 通义千问 —— 阿里巴巴集团倾力打造…

某业帮六月校招后端笔试

题目一 解题思路 签到题&#xff0c;dp就行。 题目二 解题思路 这个比较烦人&#xff0c;需要处理额外的引号和括号。用DFS&#xff0c;对于每个间隙&#xff0c;插入与不插入都搜一遍。 题目三 解题思路&#xff1a; 双指针&#xff0c;左右各一个指针&#xff0c;对比长度&…

OpenLCA、GREET、R语言的生命周期评价方法、模型构建

原文链接&#xff1a;OpenLCA、GREET、R语言的生命周期评价方法、模型构建教程https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247608240&idx6&sn1b5758206d500399fe7cc69e800f61fe&chksmfa826657cdf5ef413d31557941a1c5db5cc84bba8d0f408c469e05a4118c…

#LinuxC高级 笔记一

linux命令 什么是嵌入式&#xff1f; 以应用为中心&#xff0c;以计算机技术为基础&#xff0c;软件硬件可裁剪&#xff0c;适用于对功能、可靠性、成本、体积、功耗有严格要求的专用计算机系统 计算机系统组成&#xff1f; 硬件、软件 操作系统&#xff1f; ios windows harmo…

k8s_集群搭建_k8s管理前端_dashboard安装部署---分布式云原生部署架构搭建017

然后再去安装一下一个dashboard,有了这个以后,操作k8s集群就不用 一直敲命令了 可以看到上面的命令拿过来,然后 执行就可以了 然后如果执行慢,可以直接先去下载,使用wget,然后再去 也可以在浏览器访问,把内容拿到,然后 下面是内容: # Copyright 2017 The Kubernetes Author…

登 Cell 子刊!清华大学张强锋课题组开发 SPACE 算法,组织模块发现能力领先同类工具

多细胞生物中的细胞尽管共享相同的基因组&#xff0c;但因其内部基因调控网络的差异以及与周围微环境中相邻细胞的外部信号交流&#xff0c;使得它们在形态、基因表达和功能上展现出显著的多样性。为了将细胞类型信息与其在组织内的空间位置相关联&#xff0c;空间转录组学 (Sp…

Vue86-Vuex中的getters属性

一、getters的使用 1-1、index.js中getters的书写 计算属性computed靠return获得返回值&#xff01; 1-2、组件中getters的调用 state是数据源&#xff0c;getters是拿着数据源里的东西进行一番加工。像极了&#xff1a;data和computed 二、小结