vue+onlyOffice+java : 集成在线编辑word并保存
1.docker部署onlyOffice
1.1拉取最新版onlyOffice镜像
sudo docker pull onlyoffice/documentserver
1.2运行以下命令运行容器
其中 -v 后的第一部分是挂载自己的linux的哪个目录
# 启动docker容器,默认启动端口为80,可以进行修改 docker run -i -t -d -e TZ="Asia/Shanghai" -p 6831:80 --restart=always \-v /usr/local/docker/document/logs:/var/log/onlyoffice \-v /usr/local/docker/document/data:/var/www/onlyoffice/Data \-v /usr/local/docker/document/lib:/var/lib/onlyoffice \-v /usr/local/docker/document/db:/var/lib/postgresql onlyoffice/documentserver
运行完容器后开始编写代码
2.前端vue代码:
2.1public文文件夹下index.html引入对应的脚本
其中的ip地址和端口改成自己的
<script type='text/javascript' src='http://192.168.59.164:6831/web-apps/apps/api/documents/api.js'></script>
2.2 vue组件代码
<!--onlyoffice 编辑器--> <template><div id='vabOnlyOffice'></div> </template><script> export default {name: 'VabOnlyOffice',props: {option: {type: Object,default: () => {return {}},},},data() {return {doctype: '',docEditor: null,}},beforeDestroy() {if (this.docEditor !== null) {this.docEditor.destroyEditor();this.docEditor = null;}},watch: {option: {handler: function(n) {this.setEditor(n)this.doctype = this.getFileType(n.fileType)},deep: true,},},mounted() {if (this.option.url) {this.setEditor(this.option)}},methods: {async setEditor(option) {if (this.docEditor !== null) {this.docEditor.destroyEditor();this.docEditor = null;}this.doctype = this.getFileType(option.fileType)let config = {document: {//后缀fileType: option.fileType,key: option.key ||'',title: option.title,permissions: {edit: option.isEdit,//是否可以编辑: 只能查看,传falseprint: option.isPrint,download: false,// "fillForms": true,//是否可以填写表格,如果将mode参数设置为edit,则填写表单仅对文档编辑器可用。 默认值与edit或review参数的值一致。// "review": true //跟踪变化},url: option.url,},documentType: this.doctype,editorConfig: {callbackUrl: option.editUrl,//"编辑word后保存时回调的地址,这个api需要自己写了,将编辑后的文件通过这个api保存到自己想要的位置lang: option.lang,//语言设置//定制customization: {autosave: false,//是否自动保存chat: false,comments: false,help: false,// "hideRightMenu": false,//定义在第一次加载时是显示还是隐藏右侧菜单。 默认值为false//是否显示插件plugins: false,},user:{id:option.user.id,name:option.user.name},mode:option.model?option.model:'edit',},width: '100%',height: '100%',token:option.token||''}// eslint-disable-next-line no-undef,no-unused-varsthis.docEditor = new DocsAPI.DocEditor('vabOnlyOffice', config)},getFileType(fileType) {let docType = ''let fileTypesDoc = ['doc', 'docm', 'docx', 'dot', 'dotm', 'dotx', 'epub', 'fodt', 'htm', 'html', 'mht', 'odt', 'ott', 'pdf', 'rtf', 'txt', 'djvu', 'xps',]let fileTypesCsv = ['csv', 'fods', 'ods', 'ots', 'xls', 'xlsm', 'xlsx', 'xlt', 'xltm', 'xltx',]let fileTypesPPt = ['fodp', 'odp', 'otp', 'pot', 'potm', 'potx', 'pps', 'ppsm', 'ppsx', 'ppt', 'pptm', 'pptx',]if (fileTypesDoc.includes(fileType)) {docType = 'text'}if (fileTypesCsv.includes(fileType)) {docType = 'spreadsheet'}if (fileTypesPPt.includes(fileType)) {docType = 'presentation'}return docType}}, } </script>
2.3父组件中开始引用
要记得注册组件
<div class='qualityManual-container'><el-dialog :visible.sync="openOffice" width="800px" height="800px" append-to-body ><div class='qualityManual-container-office'><only-office :option='option' /></div></el-dialog></div>
对应的data中的属性:
openOffice:false,//参考vabOnlyOffice组件参数配置option: {key:"",url: '',isEdit: '',fileType: '',title: '',lang: '',isPrint: '',user: { id:null,name:''}},
对应的method中添加方法(这个方法可以在需要的地方引用):
需要注意的是,这里的ip必须这样填(自己天自己的),因为作为docker运行的onlyoffice,需要这样访问本地linux服务器中的服务程序
注:(自己在本地测试时无法通过localhost进行测试运行)
modifyTem(row){this.getFile(row.id)},getFile(id) {this.openOffice = truethis.show = false// getAction('/file/selectById', { id: this.id }).then(res => {this.option.isEdit = true // https://dsgrcdnblobprod5u3.azureedge.net/catalog-assets/zh-cn/a32a147f-1f69-4fd5-8a39-c25b2a0093e8/tf67429532_wac-987650ec15fa.docxthis.option.lang = 'zh-CN'this.option.url = 'http://192.168.59.164:8080/notemode/notemodeltypeenum/download/'+idthis.option.title = '笔录模板'this.option.fileType = 'docx'this.option.isPrint = falsethis.option.user= { id:12,name:'张三'}this.option.editUrl = "http://192.168.59.164:8080/notemode/notemodeltypeenum/save/"+id// this,option.key="11111"// })},close() {this.show = false},
对应的样式
<style > .qualityManual-container-office {width: 100%; /* 确保容器宽度充满整个父元素 */height: 800px; /* 根据需要调整高度 */overflow: hidden; /* 避免内部内容溢出 */ }</style>
3.对应的后端代码
1.dowload 方法是作为流进行文件数据的返回
2.save方法是对在线编辑后对于word的保存回调方法,在vue中有对应url回调地址的设置选项
注意:回调的时候,onlyOffice是通过一个地址(url)让你进行去下载。
有一些是测试时的代码,没有删掉,请大家注意甄别。
@GetMapping("/download/{id}")public void download(@PathVariable("id")Long id, HttpServletRequest request, HttpServletResponse response) throws Exception {Notemodeltypeenum notemodeltypeenum = notemodeltypeenumService.selectNotemodeltypeenumByID(id);String filePath = "/a.docx";int profileIndex = notemodeltypeenum.getContentStr().indexOf("/profile") + "/profile".length();String subPath = notemodeltypeenum.getContentStr().substring(profileIndex);filePath = RuoYiConfig.getProfile()+subPath;//本地文件 // String configPath = RuoYiConfig.getAttachPath(); // filePath = configPath + attachment.getVirtualpath();File file = new File(filePath);if (file.exists()) {// String filename = attachment.getFilename();response.setContentType("application/octet-stream");response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("a.docx", "utf-8"));response.setCharacterEncoding("utf-8");response.setContentLength((int) file.length());byte[] buff = new byte[(int) file.length()];BufferedInputStream bufferedInputStream = null;OutputStream outputStream = null;try {outputStream = response.getOutputStream();bufferedInputStream = new BufferedInputStream(new FileInputStream(file));int i = 0;while ((i = bufferedInputStream.read(buff)) != -1) {outputStream.write(buff, 0, i);outputStream.flush();}} catch (IOException e) {e.printStackTrace();} finally {try {bufferedInputStream.close();} catch (IOException e) {e.printStackTrace();}}}}@PostMapping("/save/{id}")public void save(@PathVariable("id")Long id,@RequestParam Map<String, String> map, HttpServletRequest request, HttpServletResponse response) {Notemodeltypeenum notemodeltypeenum = notemodeltypeenumService.selectNotemodeltypeenumByID(id);PrintWriter writer = null;String body = "";try {writer = response.getWriter();Scanner scanner = new Scanner(request.getInputStream());scanner.useDelimiter("\\A");body = scanner.hasNext() ? scanner.next() : "";scanner.close();} catch (Exception ex) {writer.write("get request.getInputStream error:" + ex.getMessage());return;}if (body.isEmpty()) {throw new GlobalException("ONLYOFFICE回调保存请求体未空");}JSONObject jsonObj = JSONObject.parseObject(body);int status = (Integer) jsonObj.get("status");int saved = 0;String key = jsonObj.get("key").toString();if (status == 2 || status == 3 || status == 6) //MustSave, Corrupted{String downloadUri = (String) jsonObj.get("url");System.out.println(downloadUri);try {String fileName = generateUniqueFileName(extractFileName(notemodeltypeenum.getContentStr()));String savePath = RuoYiConfig.getProfile()+"/"+fileName;downloadFile(downloadUri,savePath);// 更新原数据的文件地址String s = replacePathAfterProfile(notemodeltypeenum.getContentStr(), "/" + fileName);notemodeltypeenum.setContentStr(s);notemodeltypeenumService.updateNotemodeltypeenum(notemodeltypeenum);} catch (Exception ex) {saved = 1;ex.printStackTrace();}}writer.write("{\"error\":" + saved + "}");}public static void downloadFile(String fileUrl, String saveDir) {try {URL url = new URL(fileUrl);URLConnection connection = url.openConnection();// 5000 milliseconds is an example timeout valueconnection.setConnectTimeout(5000);connection.setReadTimeout(5000);try (BufferedInputStream in = new BufferedInputStream(connection.getInputStream());FileOutputStream fileOutputStream = new FileOutputStream(saveDir)) {byte[] dataBuffer = new byte[1024];int bytesRead;while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {fileOutputStream.write(dataBuffer, 0, bytesRead);}}System.out.println("File downloaded successfully: " + saveDir);} catch (IOException e) {System.out.println("Error downloading the file: " + e.getMessage());e.printStackTrace();}} // // public static void main(String[] args) { // downloadFile("https://dsgrcdnblobprod5u3.azureedge.net/catalog-assets/zh-cn/a32a147f-1f69-4fd5-8a39-c25b2a0093e8/tf67429532_wac-987650ec15fa.docx","D:/新建文件夹/87650ec15fa.docx"); // }public static String generateUniqueFileName(String originalFilename) {String fileExtension = ""; // 文件扩展名int i = originalFilename.lastIndexOf('.');if (i > 0) {fileExtension = originalFilename.substring(i);}return UUID.randomUUID().toString() + fileExtension; // 生成带有扩展名的唯一文件名}public static String extractFileName(String url) {// 检查url是否为空if (url == null || url.isEmpty()) {return "";}// 查找最后一个斜杠的位置int lastIndex = url.lastIndexOf('/');if (lastIndex == -1) {return ""; // 如果没有找到斜杠,返回空字符串}// 从最后一个斜杠之后的位置开始提取子字符串return url.substring(lastIndex + 1);}public static String replacePathAfterProfile(String url, String newPath) {if (url == null || url.isEmpty()) {return url; // 或抛出异常,取决于你的错误处理策略}// 找到"profile"后的第一个斜杠的索引int profileIndex = url.indexOf("/profile");if (profileIndex == -1) {return url; // 如果找不到"profile",返回原始URL}// 计算"profile"之后的部分开始的索引int startReplaceIndex = profileIndex + "/profile".length();// 构造新的URLreturn url.substring(0, startReplaceIndex) + newPath;}
参考文章:
onlyoffice+vue实现在线预览在线编辑_onlyoffice vue-CSDN博客
SpringBoot集成onlyoffice实现word文档编辑保存-阿里云开发者社区
相关文章:
vue+onlyOffice+java : 集成在线编辑word并保存
1.docker部署onlyOffice 1.1拉取最新版onlyOffice镜像 sudo docker pull onlyoffice/documentserver 1.2运行以下命令运行容器 其中 -v 后的第一部分是挂载自己的linux的哪个目录 # 启动docker容器,默认启动端口为80,可以进行修改 docker run -i -t …...

linux上用Jmter进行压测
在上一篇中安装好了Jmeter环境,在这一篇中将主要分享如何使用jmeter在linux中进行单机压测。 1.项目部署 在这里我们先简单部署一下测试环境,所用到的项目环境是个jar包,先在linux上home目录下新建app目录,然后通过rz命令将项目ja…...

【Java代码审计】代码审计的方法及常用工具
【Java代码审计】代码审计的方法及常用工具 代码审计的常用思路代码审计辅助工具代码编辑器测试工具反编译工具Java 代码静态扫描工具 代码审计的常用思路 1、接口排查(“正向追踪”):先找出从外部接口接收的参数,并跟踪其传递过…...

我国吻合器市场规模不断扩大 国产化率有所增长
我国吻合器市场规模不断扩大 国产化率有所增长 吻合器是替代手工切除或缝合的一种医疗器械,其工作原理与订书机十分相似,可利用钛钉对组织进行离断或吻合。经过多年发展,吻合器种类逐渐增多,根据手术方式不同,吻合器大…...

深度剖析Comate智能产品:科技巧思,实用至上
文章目录 Comate智能编码助手介绍Comate应用场景Comate语言与IDE支持 Comate安装步骤Comate智能编码使用体验代码推荐智能推荐生成单测注释解释注释生成智能问答 Comate实战演练总结 Comate智能编码助手介绍 市面上现在有很多智能代码助手,当时互联网头部大厂百度也…...

Centos 7.9 配置VNCServer实现远程vnc连接
文章目录 1、Centos安装图形界面1.1、安装X Windows System图形界面1.2、安装GNOME图形界面 2、VNC SERVER配置2.1、VNC SERVER安装2.2、VNC SERVER配置1)创建vnc配置文件2)修改配置文件内容3)完整配置文件参考 2.3、设置vnc密码2.4、配置防火…...
设计模式-08 - 模板方法模式 Template Method
设计模式-08 - 模板方法模式 Template Method 1.定义 模板方法模式是一种设计模式,它定义了一个操作的骨架,而由子类来决定如何实现该操作的某些步骤。它允许子类在不改变算法结构的情况下重定义算法的特定步骤。 模板方法模式适合用于以下情况&am…...
Android 适配阿拉伯语之vector图标镜像
Android 适配阿拉伯语之vector图标镜像 android:autoMirrored“true” 属性简单而直接的方法来自动处理 RTL 环境中图标的翻转。 使用 android:autoMirrored“true” 在 Vector Drawable 中是一种非常方便的方法,因为它允许你使用相同的 drawable 资源来适应不同的…...

推荐4个可用的github国内镜像
Github是全球最大的代码托管云平台,超过1亿用户在平台上分享代码及数据,深受生物信息学软件开发者的喜爱,并且现在发表文章,若涉及到代码,编辑还要求我们把代码及数据存放在github上,以便检查数据的真实性和…...

从项目开始学习Vue——02(若依框架)
往期: 从项目开始学习Vue——01 目录标题 一、基础插件(一)路由Vue Router(二)导航守卫(路由拦截器)二、Vuex(一)什么是VuexVuex的部分介绍内容: (…...

使用JavaScript日历小部件和DHTMLX Gantt的应用场景(二)
DHTMLX Suite UI 组件库允许您更快地构建跨平台、跨浏览器 Web 和移动应用程序。它包括一组丰富的即用式 HTML5 组件,这些组件可以轻松组合到单个应用程序界面中。 DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表,可满足项目管理应用…...

springboot整合redis多数据源(附带RedisUtil)
单数据源RedisUtil(静态) 单数据源RedisUtil,我这里implements ApplicationContextAware在setApplicationContext注入redisTemplate,工具类可以直接类RedisUtil.StringOps.get()使用 package com.vehicle.manager.core.util;import com.alibaba.fastjson.JSON; import lombok.e…...
Web实时通信的学习之旅:SSE(Server-Sent Events)的技术详解及简单示例演示
文章目录 一、什么是SSE二、SSE技术的基本原理三、SSE适用于场景四、Node服务端示例1、协议2、格式3、事件3.1、事件3.2、事件唯一标识符3.3、重连事件 4、具体示例 五、客户端示例1、检测客户端是否支持SSE2、创建客户端连接3、事件监听4、接收事件5、自定义事件6、错误处理7、…...

Apache Flume事务
Apache Flume 中的事务处理是指 Flume Agent 在处理事件流时的一种机制,用于确保数据的可靠传输和处理。 1. 事务概述: Flume 中的事务是指一组事件的传输和处理,这些事件在传输过程中要么全部成功完成,要么全部失败࿰…...

根据部门id删除该部门下的员工(事务)
application.properties: 或: application.yml: 新表: 日志对象类: 日志service类: 日志service接口: 日志mapper类: 部门service类: 员工mapper类:...
Java之String类
一、String类常用方法 1.引用类型的比较 我们知道在Java中两个引用遍历是不能用" "号来比较的,而String类重写了父类objects的equals方法, 实现了引用类型的比较 例子 import java.util.Scanner; public class Main { public static void…...
es终止快照恢复进程的方法
方法1、删除索引可以终止,恢复进程。 DELETE index_* // 按通配符删除以index_开头的索引 DELETE _all // 删除全部索引 POST *,-.*/_close 关闭索引 POST *,-.*/_open 打开索引 DELETE *,-.* 删除全部索引方法2、强制重启es 集群也可也终…...
ubantu安装rabbbitmq
ubantu安装rabbbitmq 安装Erlang1、在linux下直接安装2、上传Erlang文件后解压 安装rabbitmq开启web管理接口创建用户及修改guest密码,删除guest默认账号 安装Erlang 1、在linux下直接安装 #运行以下命令直接安装: sudo apt-get install erlang#可运行…...

了解 条码工具 Dynamsoft 在条码读取器中的形态运算
在图像处理中,术语形态学是指分析形状以填充小孔、去除噪声、提取轮廓等的一组操作。形态学操作很像空间卷积中的过滤过程。有两个部分在起作用:结构元素和预定义的计算规则。 点击下载Dynamsoft最新版https://www.evget.com/product/3691/download 结…...

NIO和NIO.2对比
Java NIO (New Input/Output) 是从Java 1.4版本开始引入的一个新的I/O API,用于替代原来的BIO(Blocking I/O)API。NIO提供了更加灵活和高效的网络通信方式,特别适合于高吞吐量的网络编程。NIO的主要特点是非阻塞模式,它…...

19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...

如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...

Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...