ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SpringBoot集成OnlyOffice:实现文档在线预览与编辑的完整指南

SpringBoot集成OnlyOffice:实现文档在线预览与编辑的完整指南 1. 选型判断在线编辑方案那么多为什么最终落在onlyoffice先交代一下我遇到这个需求的场景。业务方提了一个很常见的要求要在网页端直接预览和编辑Word、Excel、PPT并且编辑完要能自动同步回服务器。原话是就像腾讯文档那样但我们文件都在自己库里不能上传到别人服务器。用户数不大几百人以内不要求多人实时协同但要求能打开、能改、能存回去。这个需求看起来简单真正做起来涉及三条路线一是接企业微信/钉钉自带的在线文档能力省事但被平台绑死文件流转还得走它们的接口二是用前端vue-office、docx-preview这类纯前端预览方案预览倒是没问题但编辑能力基本没有顶多做一个假的可编辑文本框再拼凑保存三是自建一套可嵌入的文档服务最成熟的开放方案就是onlyoffice。我最后选了onlyoffice核心原因有三个。第一它支持把文档服务器嵌到自己的页面里也就是前端一个iframe所有操作在iframe里完成但token、权限、保存回调都归后端管数据链路是完整的文件存在你自己的存储里onlyoffice只负责渲染和编辑的临时态。第二它有明确的编辑状态机回调机制保存时机、谁最后改的、改完该干嘛都有协议可循。第三它支持在线转换格式比如doc转pdf、xls转csv这个在很多业务里是刚需。这套架构有个容易误解的地方我得提前说清楚onlyoffice分两部分一个是Document Server文档服务器负责渲染、编辑、格式转换这些重活通常用Docker跑在一台独立机器上另一个是集成层也就是你的SpringBoot后端和前端页面负责把文件内容交出去、接收回调、存回文件。onlyoffice本身不存你的业务文件它只是个加工车间。很多人第一次集成时以为onlyoffice会帮忙管理文件存储其实不会所有文件还是在你自己手里这点想清楚后面很多设计就好做了。适合看这篇文章的人大致就三种一是公司要做一个带在线预览编辑的后台系统正处在选型阶段的二是已经决定用onlyoffice但Docker部署那步就卡住了尤其是Windows环境还有依赖报错三是SpringBoot后端已经写好但对文档回调状态码、强制保存这类机制不够熟、总是对不上号的。2. 部署onlyoffice文档服务器先跑起来再处理三个隐蔽坑2.1 一条Docker命令启动最小可用实例onlyoffice官方推荐的方式就是Docker。部署一台文档服务器在Linux上其实很轻量一条命令就能起一个能用的实例sudo docker run -i -t -d -p 80:80 --restartalways \ -e JWT_ENABLEDtrue \ -e JWT_SECRETmy-super-secret-change-me \ -v /app/onlyoffice/logs:/var/log/onlyoffice \ -v /app/onlyoffice/data:/var/www/onlyoffice/Data \ -v /app/onlyoffice/lib:/var/lib/onlyoffice \ -v /app/onlyoffice/db:/var/lib/postgresql \ onlyoffice/documentserver:latest你需要重点关注的是-p 80:80。很多公司机器上80端口早就被nginx占了我建议第一次实验时直接映射到独立端口避免跟现有服务打架sudo docker run -i -t -d -p 8089:80 --restartalways \ -e JWT_ENABLEDtrue \ -e JWT_SECRETmy-super-secret-change-me \ --name onlyoffice-ds \ onlyoffice/documentserver:latest启动后浏览器访问http://服务器IP:8089能看到一个包含ONLYOFFICE Document Server is running字样的欢迎页说明成功了。注意如果你是Windows环境我可以负责任地说能用Docker Desktop就用Docker Desktop不要试图在Windows上直接安装deb/rpm包onlyoffice官方并未对Windows原生支持提供可靠安装包强行装会踩到各种依赖和内核兼容的坑。启动之后还能看到一个只读的欢迎页面很多人以为这就算集成了其实不是这只是一个裸服务。真正的任务是你自己的系统要往这个服务里塞文档链接和配置进去这放到后面第3章讲。2.2 font依赖与中文字体部署完不装字体的后果很严重不少人在包安装方式下会碰到fonts-dejavu依赖报错比如提示onlyoffice-documentserver depends on fonts-dejavu; however: Package fonts-dejavu is not installed。这其实不是onlyoffice的问题是它内部渲染PDF和图片预览时依赖dejavu字体库。Docker镜像里已经预制好了这个字体所以在Docker方式下基本不会遇到这个报错。真正容易忽略的是中文字体。文档服务器默认自带的是dejavu字体对中文字符的渲染很弱如果服务器上没装任何中文字体你上传一个中文Word文档进去预览时会出现大量方块和乱码或者段落位置错乱。这个在文档服务器刚起来时不会暴露等第一次拿中文doc测试时才炸。解决办法是在容器里挂载中文字体目录。在宿主机准备一个字体目录把Windows的C:\Windows\Fonts里的simsun.ttc、msyh.ttc这些文件复制过去注意版权内网使用通常没问题然后这样启动sudo docker run -i -t -d -p 8089:80 --restartalways \ -e JWT_ENABLEDtrue \ -e JWT_SECRETmy-super-secret-change-me \ -v /usr/share/fonts/onlyoffice:/usr/share/fonts/truetype/custom:ro \ --name onlyoffice-ds \ onlyoffice/documentserver:latest挂载完成后要进入容器重建字体缓存sudo docker exec onlyoffice-ds fc-cache -f -v sudo docker restart onlyoffice-ds如果你部署的时候急着要去联调接口这一步千万别跳过。字体问题不解决后面每次预览中文文档都会怀疑是集成代码不对实际上全是字体的事。2.3 Windows下把onlyoffice安装在D盘的实操办法onlyoffice怎么安装在d盘这词被搜得很多。如果你用的是Docker Desktoponlyoffice镜像和它的容器数据默认会放在C盘的用户目录下镜像体积好几个GB加上容器数据C盘很快就满了。想把它挪到D盘不是在启动命令里改一个参数就行而是要动Docker Desktop的虚拟磁盘位置。网上最省事的办法是给Docker Desktop设置里改磁盘镜像位置。在Docker Desktop的Settings - Resources - Advanced里有一个Disk image location把它从C盘的%LOCALAPPDATA%\Docker\wsl\data\ext4.vhdx改到D盘目录比如D:\DockerData。这一步会让Docker Desktop重新建一个空的虚拟磁盘你原来的镜像全都没了所以操作前要先把需要的镜像导出或者确认可以重新拉取。还有一个更灵活的做法只针对单个容器迁移先用docker inspect拿到当前数据卷的位置把整个/var/lib/docker/volumes或指定数据卷目录复制到D盘然后在启动命令里用-v D:\DockerData\onlyoffice:/var/www/onlyoffice/Data这种挂载方式把数据目录显式指到D盘。容器本身是无状态的重新拉一次镜像也就几分钟真正重要的是数据映射。最稳的组合是镜像放默认位置无所谓数据目录一定要显式挂载到D盘这样不管C盘怎么满你的文档缓存和历史记录都安全。3. SpringBoot后端集成从生成Token到回调落库的完整链路3.1 文档URL与用户身份先把基础结构理清楚onlyoffice的集成模型里前端会向你的后端要一个编辑或预览这个文档的凭证这个凭证就是一段配置JSON。你可以简单理解成你后端告诉onlyoffice我要打开这个文件打开的人是谁他能干什么onlyoffice根据这些信息去拉取文件并渲染到iframe里。一个最典型的配置JSON长这样{ document: { fileType: docx, key: 9a8e7c56-xxxx-xxxx-xxxx-xxxxxxxxxxxx, title: 年度总结报告.docx, url: https://your-backend.com/api/onlyoffice/file/9a8e7c56 }, documentType: word, editorConfig: { callbackUrl: https://your-backend.com/api/onlyoffice/callback, lang: zh-CN, user: { id: 1001, name: 张三 } } }这里的url字段是onlyoffice文档服务器主动去你后端拉取的文件内容地址用户浏览器不直接经手文件内容所以这个地址是后端到后端的在内网环境里甚至可以写内网IP。key是文档的唯一标识onlyoffice用它来管理缓存。这个key非常关键同一个文档的key如果变了文档服务器会认为是新文档就丢失编辑状态如果同一个key却对应了不同的文件内容又会导致编辑冲突。我的建议是用业务表里的文件ID加更新时间戳生成唯一key比如file_123_20240615103000。callbackUrl是通知地址用户点保存或文档服务器做自动保存时会往这个地址发一个POST请求你的后端在这里接收状态变更做实际的落库。3.2 为什么要开启JWT不签名的后果就是被刷接口从7.x版本开始onlyoffice对JWT的支持越来越严格。你可能会觉得我就在内网部署不签名也没事吧但这个接口设计有个天然的风险只要有人拿到文档URL和你的服务地址就能伪造一个编辑配置让onlyoffice去拉他自己服务器上的恶意文件甚至通过回调地址探测你内网的端口。所以现在官方默认建议开启JWT并且强烈建议在所有环境都开。SpringBoot这边生成Token的逻辑很简单核心是选对签名算法。我用的是HS256密钥跟部署onlyoffice时配置的JWT_SECRET保持一致。下面是生成token的工具类注意它对配置JSON做序列化时要保持字段顺序稳定不要把null字段也序列化进去否则签名前和解析时对不上Component public class OnlyofficeJwtUtil { private final SecretKey key; public OnlyofficeJwtUtil(Value(${onlyoffice.jwt-secret}) String secret) { this.key Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8)); } public String createToken(MapString, Object payload) { return Jwts.builder() .setClaims(payload) .signWith(key, SignatureAlgorithm.HS256) .compact(); } public Claims parseToken(String token) { return Jwts.parserBuilder() .setSigningKey(key) .build() .parseClaimsJws(token) .getBody(); } }这里有个容易踩的坑JWT_SECRET不要太短。HS256的密钥最好至少32字节如果少于这个长度部分jwt库会直接抛异常。用一段随机生成的字符串比如openssl rand -base64 48生成的结果然后前后端部署和开发都保持一致。3.3 生成编辑页面地址后端返回完整iframe src很多人以为集成就是后端返回一个文档URL前端拿过来往iframe里一塞就行。实际上前端iframe的src指向的是onlyoffice的web-app地址并且要把上面的配置JSON当作_storage参数传过去。也就是说你后端要做的事是根据文档信息生成配置JSON签名成token然后拼出一个完整的URL给前端。我在Controller里是这样写的GetMapping(/preview/{fileId}) public ResultString preview(PathVariable Long fileId) { // 1. 查业务表拿到文件存储路径、文件名、文件类型 FileMeta meta fileMetaService.getById(fileId); // 2. 构造onlyoffice需要的配置JSON MapString, Object config buildEditorConfig(meta); // 3. 签名得到token String token onlyofficeJwtUtil.createToken(config); // 4. 生成前端iframe要用的src String editorUrl onlyofficeConfig.getServerUrl() /web-apps/apps/api/documents/api.js ?documentType resolveDocType(meta.getFileType()); MapString, Object result new HashMap(); result.put(token, token); result.put(editorUrl, editorUrl); result.put(config, config); return Result.ok(result); }前端拿到这个结果后不是直接把这个editorUrl当iframe的src而是要先引入api.js然后调用new DocsAPI.DocEditor(placeholder, config)来初始化编辑器。这个api.js本质上是一个JS加载器它会读取你传入的config再帮你在指定的div里创建iframe。所以正确的集成姿势是后端把config和token返回给前端前端把token塞回config里再调DocsAPI初始化。这里也有一个从SpringBoot集成角度特别值得注意的点document.url指向的文件下载接口不能在公网随便暴露但要保证onlyoffice文档服务器能访问到。如果前后端分离部署这个下载接口最好做成内网可访问的专用接口或者至少要用临时签名URL比如带一个5分钟有效期的查询参数不要让文件永久裸奔在URL里。我看过不少项目把这个下载接口写成任何人都能传一个fileId就下载的这是典型的越权漏洞。3.4 回调处理状态码对应什么动作onlyoffice文档服务器在多种时机下会向你配置的callbackUrl发送回调这个回调是理解整个集成逻辑的钥匙。它的典型JSON长这样{ status: 2, key: file_123_20240615103000, url: https://onlyoffice-server/cache/xxxx/output.docx, users: [1001], actions: [edit] }状态码的含义整理了表如下状态码状态含义你需要做的动作1文档已被编辑正在保存中一般不需要处理等status22文档保存成功回调里带有新的文件下载地址根据url把新文件下载下来替换旧文件更新数据库3文档保存出错记日志标记保存失败通知用户4用户关闭了编辑器且没有修改不需要落库但可以更新在线状态6文档正在编辑可以做实时在线人数展示7强制保存完成回调里带forcesave字段跟status2类似也需要替换文件最需要小心的是status2和status7的区别。status2是正常保存或者用户主动点保存回调里的url是本次保存的临时文件地址status7是强制保存比如管理员触发的强制保存指令或者编辑时间到了自动保存它会额外带一个forcesave为true的字段。如果是status7你也必须去下载url指向的文件落库不能忽略否则用户等了一小时你数据库里还是初版。回调处理在SpringBoot里的写法有一个天然的复杂性这个接口不能被用户伪造数据打进来也不能被普通登录拦截器卡住。我的建议是单独做一个白名单路径比如/api/onlyoffice/callback关闭登录校验但加一层JWT校验——onlyoffice发来的回调是没有你的登录cookie的它只有文档服务器自己的身份。实操上可以在回调请求里校验ip来源只允许文档服务器的内网IP访问这比什么都强。下面是我实际在项目里使用的回调处理方法骨架PostMapping(/callback) public ResponseEntityVoid callback(RequestBody OnlyofficeCallback callback) { // 1. 校验key是否存在避免垃圾请求 FileMeta meta fileMetaService.getByKey(callback.getKey()); if (meta null) { return ResponseEntity.notFound().build(); } // 2. 根据状态码分流 switch (callback.getStatus()) { case 2, 7 - { // 下载新内容覆盖旧文件更新版本号 byte[] content downloadFromUrl(callback.getUrl()); fileStorageService.store(meta.getStorePath(), content); fileMetaService.updateVersion(meta.getFileId(), callback.getKey()); } case 3 - log.error(文档保存失败: {}, callback.getKey()); default - log.debug(未处理状态: {}, callback.getStatus()); } // 3. 必须返回{error:0}否则文档服务器会一直重试 return ResponseEntity.ok().build(); }4. 强制保存与定时保存关于保存机制的本质理解4.1 用户点没点保存你要怎么知道只处理用户手动点保存是远远不够的。真实业务里绝大多数用户编辑完文档后直接关掉浏览器标签页根本不会去点那个保存按钮。如果只依赖用户主动保存数据丢失是必然的。onlyoffice文档服务器默认有一个自动保存机制每过一段时间如果文档有改动会自动触发一次保存回调里就是status2或status6/7组合。这个机制极大兜底了用户直接关闭页面的场景。你真正该做的是不要在前端给用户提供额外的保存按钮因为编辑器自带保存和自动保存你再做一个外层保存按钮反而会造成认知混乱。唯一需要做的是在页面关闭之前用onlyoffice的docEditor.destroy()方法做一次安全的关闭前清理。如果你需要严格保证强制落库可以调用文档命令服务Document Command Service里的forcesave指令。这个服务走的是另一个API不在编辑器的JWT体系里需要单独管理。基本流程是构造一个POST请求指向https://onlyoffice-server/coauthoring/CommandService.ashx。请求体里带上c命令名比如forcesave、key文档key。请求本身要带上JWT签名签名的密钥依然是JWT_SECRET但payload不是你之前给前端的那种config结构而是整个请求体本身。实测下来forcesave生效后等一小段时间通常几秒文档服务器就会往callbackUrl发送一条status7的回调你的落库逻辑跟status2一模一样。这个机制特别适合用在管理员在后台上点击锁定文档或审批流程结束时需要立即把当前状态存下来这类场景。4.2 外部按钮触发回调当前页面的更新与版本号有的需求是后台上有一个刷新文档预览按钮希望在外部导入新版本的文档后能让正在打开这个文档的用户界面刷新。这个场景在onlyoffice里叫刷新文件版本同样走命令服务POST /coauthoring/CommandService.ashx { c: refresh, key: file_123_20240615103000 }执行成功后打开文档的用户界面会自动提示文档已被更新用户可以重新加载。这个特性特别适合多人协作时的管理员强制同步场景。还有一类需求是外部按钮后需要立刻拿到一份PDF或特定格式的预览结果这时候可以用命令服务里的convert命令在线把docx转成pdf。注意这个转换能力对格式的支持度不是100%完美转简单文档没问题碰到带复杂宏、域、嵌入式VBA的文档排版会有偏差不能用它替代真正的兼容性测试。4.3 定时自动落库的兜底策略前面讲的是onlyoffice自带的保存机制。但作为一个业务系统我强烈建议你再设计一道自己的兜底定时任务定时检查那些打开超过一定时间但数据库版本号没变的文档强制触发一次forcesave然后检查回调是否落库成功。为什么要有这层兜底因为onlyoffice的自动保存机制对于打开后无操作的文档是有一个静默判定时间的。如果用户在编辑器里停留了很久但没有改动文档服务器不会触发保存回调如果用户改了内容但从未点保存自动保存也会在编辑后的某个时间点触发。这两种情况之间有一段“灰区”在这个灰区里如果服务重启或断网未保存的内容就可能丢。我的实现方式很简单新建一张doc_edit_session表记录用户打开文档的时间、最后心跳时间、最后保存版本号。一个定时任务每分钟扫一次发现某条会话的lastSaveVersion小于lastModifyVersion就调用forcesave然后把是否落库成功写回表里。这套方案实测很稳等于在onlyoffice的兜底机制之外又加了业务层自己的保险。5. 前端iframe集成参数与多格式适配要点5.1 初始化方式别把iframe写死在HTML里onlyoffice官方推荐前端通过加载api.js来初始化编辑器而不是手动写一个iframe元素。原因在于api.js内部还要做cdn资源加载、跨域通信、token传递、会话心跳等一堆事情。手写iframe基本等于放弃所有的生命周期管理。正确的步骤就三行div iddocEditor/div script srchttps://onlyoffice-server/web-apps/apps/api/documents/api.js/script script const config { document: { fileType: docx, key: file_123_20240615103000, title: 年度总结报告.docx, url: https://your-backend.com/api/onlyoffice/file/123 }, documentType: word, editorConfig: { callbackUrl: https://your-backend.com/api/onlyoffice/callback, lang: zh-CN, user: { id: 1001, name: 张三 } } }; const docEditor new DocsAPI.DocEditor(docEditor, config); /scriptmode参数这里要特意提一下它有edit和view两种值。如果你只是做预览不想要编辑菜单就设置mode: view。但要注意view模式下的回调和保存逻辑会简化很多文档服务器不会产生status2这种保存回调。所以权限设计上纯预览人群走view需要编辑的人走edit后端生成config时根据用户权限动态切换mode字段。5.2 高度自适应iframe高度永远不对怎么办onlyoffice的编辑器高度可以通过config中的height字段设置。最常见的写法是editorConfig: { height: 100%, width: 100% }但在某些前端框架里父容器高度为0或为auto时100%不会生效。我的经验是给外层div一个明确的最小高度比如min-height: 720px然后config里也一样写明确数字。如果你用的是Vue特别注意不要在v-if刚渲染完就立即初始化要等dom真的挂载后再调new DocsAPI.DocEditor。我碰到过至少两次因为初始化早于dom渲染编辑器始终不显示的问题最后都是把初始化放到nextTick或setTimeout里解决的。5.3 从格式兼容看docx、xlsx、pptx之外的杂项onlyoffice能预览的文件格式远超Office三件套包括odt、ods、odp、rtf、txt、csv等但这不代表你所有文件都能无脑塞进去。对于.doc这种老格式onlyoffice能打开但复杂样式下渲染可能有偏差。对于.wps这种国产格式它的兼容性就不那么理想。一个务实的做法是在文件上传时就做格式归一化后台用onlyoffice的命令服务或LibreOffice把非常规格式统一转成docx/xlsx/pptx或pdf然后再对外提供预览。格式转换在docker里做命令大概是sudo docker exec onlyoffice-ds docservice --convert-to pdf --output /temp/ xxx.doc实际使用中有个更简单的方式把需要转换的文件传到/var/www/onlyoffice/Data下再用转换接口。但注意命令服务转换大文件会占内存如果你服务器只有2G内存一次转100MB的PPT内存基本就溢出了。生产环境建议给onlyoffice容器至少4G内存限制否则并发编辑和转换会互相拖垮。6. 集成过程中最容易踩的雷区与完整排查链路6.1 部署起来但页面一直白屏或加载不出来这个现象第一次接触的人九成都会遇到。排查思路我建议按下面这个顺序来不要乱猜第一步检查onlyoffice文档服务器自身的健康状态。访问http://server:8089/healthcheck如果返回true说明服务活着。第二步打开浏览器DevTools看Network里有没有请求api.js以及有没有跨域报错。如果前端页面在http://localhost:8080onlyoffice在http://192.168.1.100:8089跨域问题会非常明显。onlyoffice的api.js会动态创建iframe跨域通信依赖于postMessage如果你改了它的默认域名策略需要配置容器里的ALLOW_PRIVATE_IP_ADDRESS和ALLOW_META_IP_ADDRESS这些环境变量。第三步看后端返回的document.url能不能被onlyoffice文档服务器访问到。这一步是内网环境最容易被忽视的。很多人本机开发时后端地址写的是http://localhost:8080但这个地址在onlyoffice容器里指向的是容器自己根本访问不到你的宿主机。正确做法是让document.url返回你的局域网IP或一个特殊的host映射比如http://192.168.1.100:8080/api/onlyoffice/file/123。我的排查工具是在服务器上手动执行一次那个下载接口curl -v http://192.168.1.100:8080/api/onlyoffice/file/123如果返回的是connection refused那问题基本定位了容器网络到宿主机的回环地址不通。另一个办法是启动容器时加--networkhost但Windows Docker Desktop不支持host网络所以最好的方案还是统一使用内网IP管理document.url。6.2 中文文件名导致打开失败onlyoffice对中文文件名的支持整体还不错但如果你用URL直接拼接文件名作为document.url不做URLEncoder.encode很可能在中文字符上出问题。尤其当文件名里有空格、#、这类特殊字符时URL会被截断或解析错误最终导致onlyoffice拉取不到文件页面上一直转圈。我的习惯是在所有需要嵌入到config里的URL参数上做统一编码包括文件名参数。SpringBoot里写一个工具方法private String encodeUrlParam(String value) { return URLEncoder.encode(value, StandardCharsets.UTF_8).replace(, %20); }document.title字段可以放心用中文它只用于界面展示不参与URL解析。document.url路径里的文件名部分一定要编码后再拼。6.3 上传大文件后保存回传失败生产环境遇到过一个诡异的问题小文件预览编辑保存都正常但超过20MB的文件编辑保存后回调拿不到新内容。排查下来是nginx的client_max_body_size限制。onlyoffice保存回调到业务后端时如果它先经过了一层nginx反向代理而nginx默认请求体大小只有1MB那大文件保存回调直接被nginx拦了后端自然收不到status2。解决方式是在nginx的server块里加一行client_max_body_size 200m;同时如果你后端SpringBoot的spring.servlet.multipart.max-file-size和max-request-size也卡得比较小比如默认1MB也一并改大。这几个配置改完后需要重启nginx和后端。还有一个隐藏点onlyoffice文档服务器的/cache目录如果空间不足或者Docker的磁盘被写满保存就会失败回调会儿status3。这个可以通过监控磁盘使用率来预防别让它满到影响业务才发现。6.4 SpringBoot版本和Jackson序列化的小细节如果你用的是SpringBoot 2.x默认的Jackson序列化没问题。到了SpringBoot 3.x如果用了Java 17以上的记录类型record做请求体接收要注意Jackson对record的支持需要额外配置某些情况下会把回调里的字段映射错。我的建议是对onlyoffice回调的接收对象直接用普通POJO不要用record也不要开Lombok的Builder因为这些都能正常处理但record的构造函数参数名在编译后可能丢失导致反序列化时字段全是null。另外回调的JSON里的确有users字段它的值有时是数组有时是[uid1,uid2]类型不完全固定接收时最好用ListString而不是单个String。这种小问题在联调时很影响心情提前用POJO定义好就稳了。6.5 关于启动之后页面访问地址的那些疑问热词里很多人搜onlyoffice 启动之后页面访问地址。这个地址其实就是你映射出来的那个端口比如http://192.168.1.100:8089。这个地址有几个子路径值得记一下/healthcheck健康检查。/web-apps/apps/api/documents/api.js前端集成要引用的JS。/coauthoring/CommandService.ashx命令服务强制保存、转格式、刷新版本都在这里。/web-apps/apps/api/documents/cache/files/临时缓存文件的下载路径。排查问题时能分清这几个路径效率会高得多。比如健康检查只告诉你服务活着集成失败要看的是api.js能否加载保存失败要看的是CommandService.ashx能否访问、cache目录能否读写。7. 我实际跑下来的一些心得整个springboot集成onlyoffice做完最深的体会是工具本身的API文档写得不算差但文档里几乎不教你如何把这个服务嵌到一个真实的业务系统里。业务系统要考虑的东西——权限、文件存储位置、回调鉴权、版本管理、异常兜底——这些才是实际工作量的大头。onlyoffice只负责渲染和编辑那一段它前后的业务链路全部得你自己设计。几个我认为比较关键的经验再重复一下第一document.url必须确保从onlyoffice所在的机器能访问到开发阶段可以用内网IP或临时映射不要图省事写localhost第二回调接口一定要做来源限制至少限制IP来源不要裸奔在公网第三强制保存和定时保存不是可选项是保命项尤其当你的用户习惯是改完直接关页面第四中文字体和Docker磁盘空间这两个部署层面的问题建议在进入开发联调前就处理掉不然会浪费大量排错时间。这个项目后续如果要扩展可以沿着几个方向走接入文件在线预览统计、对接统一权限中心做更细粒度的编辑权限、以及搭建一个活跃编辑会话的监控大屏。不过这些都是后话了先把文档能打开、能编辑、能保存回去这条主链路跑通就已经解决掉大多数业务方最痛的诉求了。
返回列表