多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Odoo/GoodERP附件预览实战:从选型到部署的完整指南

Odoo/GoodERP附件预览实战:从选型到部署的完整指南 前阵子一个项目上线业务部门提了个特别朴素的需求采购合同、供应商对账单、销售报价单能不能在ERP里直接预览别老让人下载到本地用Office软件打开。负责对接的同事一开始没当回事觉得“预览不就是点击附件弹个框嘛”。结果一深入才发现GoodERP和Odoo的Office附件预览功能涉及文件存储、格式转换、权限校验、在线渲染、编码处理一大堆环节踩坑踩得相当扎实。这篇文章把我这段时间的实操经验整理出来不写废话都是可以直接拿去用的东西适合正在做Odoo、GoodERP二次开发或实施的同学参考。1. 为什么ERP里必须做好这个“附件预览”1.1 附件预览不是增加功能是工作方式重构先说一个很现实的工作场景。业务员给采购主管发来一份供应商报价Excel附件挂在采购订单上。传统操作流程是下载附件 → 找到本地下载目录 → 双击打开 → 等桌面Office启动 → 看完关掉。这一套下来快的十秒慢的几十秒。一天下来一个业务员可能要看几十个附件时间损耗只是表面问题。真正要命的是三个深层次问题一是客户端软件依赖。桌面Office没装、装的是精简版、或者换了新电脑还没激活附件就打不开。移动端更是几乎无能为力手机上看个Excel要么装手机Office要么忍受WPS的广告弹窗。二是本地文件版本混乱。同一封邮件、同一个订单附件下载了三遍下载目录里全是“报价单(1).xlsx”“报价单(2).xlsx”这种文件名。等你想找最新版本根本分不清哪个是哪个。三是安全隐患。下载到本地的Office文档可能携带宏、脚本或漏洞利用载荷终端设备一旦中招整个内网都可能被拖下水。附件不落地这个风险面就大幅缩小。我在项目实施中把“附件预览”视为一个工作流重构动作而不是简单的UI优化。因为它改变了用户和单据附件之间的交互方式从“下载打开”变成“点击查看”这个过程看似简单却解决了上述三类问题。1.2 先给需求分级能看、能查、能改做预览功能之前最忌讳的就是一上来就想着“在线编辑”。我习惯把需求分成三级和业务部门一条条对齐第一级能看。点击附件即能打开支持Word、Excel、PPT、PDF几种常见格式页面内能看到内容。这是90%企业的真实需求。第二级能查。支持页面内搜索关键字、缩放、翻页甚至能对PDF做简单的批注标注。这类需求常见于法务、财务、审计岗位他们经常要在几十页合同里找指定条款。第三级能改。直接在网页里编辑文档多人协同、在线保存甚至嵌入审批流。这个级别实现成本陡然上升不仅需要引入在线办公套件服务还涉及并发编辑冲突处理、版本管理、数据库存储等一系列复杂问题。我见过一个失败的案例项目一开始就上了在线编辑能力结果上线后大多数用户只点了“查看”按钮编辑功能不仅没人用反而因为并发锁问题三天两头报错。后来把默认模式改成只读需要编辑时才由用户手动切换问题才消停。这个教训我一直记着先分级再选型才不会用力过猛。1.3 谁在用预览决定了优先级怎么做不同角色的预览诉求完全不同。采购部要看合同指定条款财务部要对账单找差异人事部要在线筛简历老板要在手机上抽查报表。这些角色对“预览”这件事的期待值不一样。我的建议是前端业务人员更看重点击速度和交互流畅度后台管理人员更看重权限管控和操作审计。因此预览功能至少要满足“所有角色都能快速查看”这个基础层再针对特定角色开放“搜索、标注、编辑”这类扩展能力。权限部分后面我会单独展开讲这里先给一个结论基础预览不限角色、人人可用高级能力按角色开放、后台可控。2. 预览方案选型五条路线怎么选2.1 浏览器直渲能应急不能救命Odoo原生本身不包含一个完整的Office在线预览组件但对PDF、PNG、JPG、纯文本这类相对简单的格式是能直接在浏览器里渲染的。原理很简单浏览器本身就支持这些格式的打开Odoo只需要把文件流输出到页面即可。这条路适合的场景是你只需要看PDF和图片Word和Excel几乎没需求。比如某个项目里只归档扫描件合同那就没必要上重型预览方案原生就能解决成本基本为零。但如果你问我“能不能让浏览器直接渲染docx/xlsx”答案会让人失望HTML标准里没有原生支持这两种格式的渲染浏览器不会自己读懂Office二进制格式。所以这条路只能应急不能当作长期方案。2.2 第三方在线预览服务接入快但有边界还有一种路线是接入第三方在线预览服务思路是把文件的URL地址传给在线预览平台由其服务端毫秒级转换成HTML或图片流返回给浏览器。接入成本确实低只需要拼接一个URL、嵌一个iframe就能获得不错的预览体验。但这条路线有一个绝大多数企业IT团队都无法接受的问题文件内容会离开内网。你把合同、报价单的URL发给外部服务等于把核心商业文档交给了第三方安全评审这关基本过不去。我仅在演示环境或POC阶段用过生产环境要上必须先走安全评估流程多数情况都会被一票否决。2.3 自建在线办公套件服务私有化的主流答案这是目前在私有化部署环境下最主流的方案在Linux服务器上部署一套开源的在线办公套件服务通过API与Odoo对接。原理是把附件投递给在线套件服务服务端用办公软件内核把文档渲染成网页返回。优点非常明显一是数据不出内网符合企业安全要求二是支持在线编辑升级空间大三是Office格式还原度较高兼容性比自研转换好得多。代价也很清晰部署和维护成本不低。在线办公套件服务对服务器资源有要求内存至少2GB起步生产稳定运行建议4GB以上多人同时编辑时还需要考虑并发扩容。此外服务本身的安装、配置、升级、监控都需要运维团队具备一定Linux基础。即便如此在国产化改造、私有化交付的场景里这条路几乎是不二之选。我之前服务的几个GoodERP项目最终无一例外都选了这条路线。2.4 官方在线预览与本地转换自研两条小众路“官方在线预览”指的是接入Office官方提供的在线网页预览接口把文件URL拼接到官方预览服务上前端用iframe加载。效果稳定还原度高对Excel、Word、PPT的支持都很好。但它的隐患和第三方在线预览服务一样——文件内容暴露给外部服务内网数据出域问题绕不过去。所以只适合文件不太敏感、且能接受外部访问的场景。“本地转换服务自研”则是有些二次开发团队不愿意引入整套办公套件而是自己写一个转换服务常驻一个进程收到转换请求时调用办公软件的导出接口把docx、xlsx转成PDF或HTML后再输出。优点是真的轻量可控性极强缺点是转换质量跟模板复杂度高度相关遇到带复杂表格、特殊字体、自动筛选的Excel经常翻车还得处理并发排队、进程挂死等工程问题。这条路我只建议有专职开发团队维护时走否则后期维护成本会让人崩溃。2.5 选型对照表我习惯用下面这张表给客户做选型这里一并分享方案接入成本维护成本数据安全在线编辑适用场景浏览器直渲极低极低高不支持仅PDF/图片场景第三方在线预览服务低低低视服务而定演示环境、非敏感文档官方在线预览低低低部分支持文件不敏感、可以出域自建在线办公套件中高中高高支持私有化、数据敏感的常规项目本地转换服务自研高高高不支持专职团队、极简场景表格里体现出来之后大多数客户都能快速对齐预期。实际选型时我90%的情况都推荐第四行自建在线办公套件服务。3. Odoo侧实现预览的技术拆解3.1 附件模型与文件路由预览链路的地基在Odoo里所有附件都挂在ir.attachment模型下。一个附件记录包含文件名、MIME类型、文件大小、关联业务模型和记录ID等关键字段。存储方式有两种默认存在数据库的二进制字段里也可以在系统配置里改为文件系统存储。预览功能的三段链路是前端拿到附件ID → 后端根据ID生成可访问的URL → 前端把URL放进预览容器。这就涉及Odoo的文件路由/web/content通用附件读取路由通过ID和文件名取原始字节。/web/image图片专用路由适合图片类附件的展示。如果你要预览的是普通Office文档通常用/web/content拿文件流就够了。第三方的预览服务或自建套件需要拿到这个文件的下载地址才能拉取并转档。这里有一个小提醒Odoo默认对二进制字段有大小限制超过一定大小的附件可能上传失败。生产环境一般建议把这个阈值调高到50MB以上但预览场景下我建议再设一个“预览阈值”比如超过30MB的附件直接提示下载而不是在线预览。原因很简单大文档转HTML时服务端的CPU和内存开销会指数级上升等待时间也会让用户失去耐心。3.2 预览入口的三种改造方式具体到Odoo界面预览入口的改造有三种做法由易到难做法一表单视图加按钮。在附件列表的视图XML里添加一个“预览”按钮绑定到一个方法前端弹出一个对话框对话框里放一个iframe指向预览URL。改动量小适合单一业务模块内快速上线。做法二自定义控制器。写一个独立的HTTP控制器接收附件ID在后端动态拼接预览服务地址并完成权限校验再把可访问URL返回给前端。这个方案开始具备通用性可以服务多个业务模块。做法三统一Web客户端动作。把预览逻辑封装成一个独立的客户端动作对系统里所有“打开附件”的操作统一拦截不管附件出现在哪个表单、哪个列表都先判断是否支持预览再决定是展示预览还是走下载。这个方案改造量大但用户体验最统一适合需要全系统铺开的场景。我实际项目的经验是起步用做法二等验证了效果再逐步演进到做法三。不要一上来就全系统改造否则改动范围和回归测试面积太大。3.3 文件大小、超时与权限三个容易被忽略的参数很多人在做预览功能时满脑子都是URL拼接和iframe嵌入但有三个参数几乎必然在后期找上门来文件大小阈值。上传限制和预览阈值要分开配置。上传限制是为了保障系统可用性预览阈值是为了保障预览体验两者混用一个参数迟早出问题。转换超时时间。大文档在服务端转档可能要几秒甚至几十秒。如果Odoo侧的HTTP请求默认超时较短就会出现“预览接口已请求但前端一直转圈”的尴尬局面。建议把预览请求的超时时间单独调长或者做成异步轮询先返回“转档中”状态前端每隔几秒查一次结果。权限校验。预览功能最容易犯的错是把附件URL暴露给无权限用户。Odoo自带的/web/content路由本身会检查记录权限但如果你用了自定义控制器或第三方服务就要自己补上校验。我的习惯是在控制器里先调用权限检查方法确认当前用户对附件记录有读权限才生成预览URL否则直接返回403。预览URL要带时效token防止被转发后长期有效。# 伪代码示例生成带时效token的预览地址 class AttachmentPreviewController(Controller): http.route(/preview/attachment, typehttp, authuser) def preview(self, attachment_idNone, **kw): attachment request.env[ir.attachment].browse(int(attachment_id)) attachment.check_access(read) token uuid.uuid4().hex request.env[preview.token].create({ token: token, attachment_id: attachment.id, expire_at: fields.Datetime.now() timedelta(minutes10) }) preview_url http://preview-server/internal?token%s % token return werkzeug.utils.redirect(preview_url)这段代码的思路比代码本身更重要先鉴权再签时效最后重定向到预览服务。顺序反了或者少了任何一步都会埋下安全隐患。4. GoodERP二次开发场景下的适配要点4.1 先分清你是哪一类GoodERP严格来说“GoodERP”并不是某一个具体产品而是一类面向国内企业、基于开源ERP框架二次开发的系统的泛称。我遇到过好几个内部项目都叫类似的名字有的直接改Odoo有的在OpenERP基础上升级还有的把前端的界面完全重写了。不同工程基于的Odoo版本、字段结构、页面组件都可能不同。做Office附件预览前先搞清楚三件事第一你的系统保留了多少Odoo原生框架。如果保留了原生模型层ir.attachment可以直接用如果业务表是自定义的需要确认附件关联字段是否还走Odoo标准机制。第二数据库里有没有自定义字段影响附件路径。有些二次开发会扩展附件表增加“来源单据类型”“附件分组”等字段取附件时要带上这些字段一起判断。第三部署环境是Windows还是Linux。GoodERP类系统部署在Windows服务器上很常见而自建在线办公套件服务多数是Linux应用跨主机通信、防火墙放行、端口映射这些都要提前规划。4.2 中文文件名与编码这个隐形坑中文文件名在预览场景里是一个高频坑几乎每个项目都会碰到。第三方预览服务拼接URL时不处理中文直接生成一个乱码地址预览就白屏了。处理办法有两条一是严格使用URL编码把文件名用encodeURIComponent处理后再拼接到地址里二是统一约定编码规范服务端接口里的业务文件名一律按UTF-8处理避免有的组件默认GBK导致二次乱码。我实际遇到过一个特别典型的案例一个客户上传了一份“供应商对账单-2025年.xlsx”预览地址里文件名编码后正常但预览服务返回的页面标题显示乱码。排查了半天发现是预览服务接收文件名时按系统默认编码解析导致内部转换失败。最后在服务端配置里强制指定UTF-8乱码问题才彻底解决。建议你在实施手册里把“文件名编码规则”写清楚并把中文文件名作为测试用例列入上线前检查清单。4.3 表单视图改造与协同软件内预览GoodERP常见的业务表单里附件列表是one2many的“文档”区域。最直观的预览入口设计是点击附件文件名直接弹预览弹窗而不是默认跳下载。很多项目就是没注意这一点用户点了半天还是下载体验自然不对。我的做法是在表单视图里配置两个动作按钮一个叫“预览”一个叫“下载”文案区分清楚按钮图标也区分开这样用户第一次使用就能理解。另一个场景是移动端。国产化项目里用户常常期望在钉钉、企业微信这类协同办公软件里直接查看ERP附件。实现思路是ERP生成一个带鉴权的预览链接通过消息卡片或H5页面嵌入到协同软件内。但这个链接必须是短时效、单次拉取的避免被转发后泄露。实际踩过的一个坑是协同软件的内置浏览器对iframe的兼容性参差不齐部分机型不支持某些预览协议头。我的解决办法是加一个中转页面先用HTTP请求探测预览服务是否可用再决定当前设备走“内嵌iframe”还是“跳转到独立页面”的展示方式。这个中转逻辑不复杂但能规避大部分移动端兼容性问题。5. 实操记录从零到一部署预览服务5.1 环境规划与安装清单下面这套组合是我在私有化项目里最常用的Odoo跑在一台应用服务器自建在线办公套件服务跑在同一内网的另一台机器两端通过HTTP内网IP互访。服务器建议配置操作系统Linux 64位不推荐直接在Windows上暴力部署内存套件服务单独分配4GB起步和Odoo应用服务器分开Java环境套件服务依赖Java运行时版本要按官方要求对齐文档处理库安装Office格式转换相关的系统依赖包这些前置条件里最容易出问题的就是Java版本。版本装高了或者装低了服务启动时可能直接报错而且报错信息还不友好多半是“Unsupported class file version”这种摸不着头脑的提示。5.2 部署步骤与验证流程整个部署流程可以收敛成六步放行防火墙端口确保Odoo服务器能访问预览服务端口。安装在线办公套件服务软件包并安装所有依赖组件。启动服务访问管理控制台确认默认页面能正常打开。创建服务管理员账号和密码。在Odoo系统参数里填入预览服务地址、账号及密钥。上传一个测试docx附件点击预览确认能正常渲染。看起来简单但我在现场经常遇到三个坑端口没放行。本地curl预览服务地址一切正常Odoo却访问不通折腾半天发现防火墙策略没有同步放行。版本不匹配。Odoo对接模块要求的API版本和服务部署的版本不一致接口调用直接404。系统参数没生效。在Odoo后台填了参数但没刷新缓存前端仍然请求旧地址看起来像“预览失效”。每完成一步就用命令行或浏览器实际验证一次不要攒到最后一起测。# 示例命令验证预览服务健康状态 curl -I http://192.168.1.10:9980/robots.txt # 预期返回200/301如果超时或拒绝连接先查防火墙和端口监听5.3 测试矩阵与体感标准上线前我建议用以下矩阵把核心文档类型过一遍文件类型小文件1MB大文件5MB特殊内容Word文档打开速度透明度与字体复杂表格、修订痕迹Excel表格打开速度大宽表滚动透视表、自动筛选、冻结窗格PPT演示打开速度动画与切换嵌入字体、视频PDF文档打开速度扫描件加载书签、目录跳转重点关注几个指标首次预览耗时是否在3秒内、中文和特殊字体是否和桌面Office一致、横向宽表在页面里是否出现裁切、扫描版PDF翻页是否卡顿。我遇到过最糟的一种情况Excel在桌面Office里显示正常一到网页预览里右侧一大片列直接裁掉了而且没有横向滚动条用户完全看不到关键营收列。后来靠调整渲染参数和放大比例才缓解。这类问题在测试阶段不暴露上线后一定会被用户揪出来。5.4 典型问题排查速查表把这段时间遇到的高频问题整理成一张速查表建议收藏备用现象排查顺序常见原因预览白屏网络连通 → URL直接访问 → 服务端日志服务地址配置错误或端口不通Word显示但Excel乱码查看服务端转换日志 → 换格式导出对比转换组件对Excel支持差异提示403检查校验逻辑 → 检查token过期 → 检查读权限控制器缺鉴权或token失效长时间加载后失败文件大小 → 超时参数 → 带宽大文件转换超时或带宽瓶颈手机端无法预览检查iframe限制 → 检查浏览器版本 → 检查HTTP/HTTPS混用移动端兼容性问题或用混合内容排查时有一个通用原则先确认预览服务本身能用再去管Odoo侧的逻辑。很多问题绕来绕去最后发现是预览服务宕机了。你先用浏览器单独访问一下预览地址一分钟就能定位一半的问题。6. 性能与安全从不翻车到防泄密6.1 并发控制与缓存在线办公套件服务对并发的容忍度不高。一次格式转换就可能把CPU占满几秒钟如果同一时间进来十个请求服务可能直接卡死。因此必须做两层保护第一层在预览服务侧做接口限流同一用户5秒内不重复发起转换请求超过并发阈值直接返回“多人预览中请稍后重试”的提示。这层保护通常通过网关或服务自带配置实现。第二层在Odoo侧做结果缓存相同附件ID、相同版本号不重复转档直接复用上次的预览结果。附件更新后要主动清理对应的预览缓存。缓存能显著降低预览服务压力尤其在财务月底对账、采购集中审价这种批量预览场景下。另外为了让并发预估更可靠我习惯在部署前做一次压测用脚本模拟10个并发预览请求观察服务响应时间和CPU占用。压测结果直接决定要给预览服务配多少资源而不是靠拍脑袋。6.2 预览鉴权与链接时效预览服务自己通常不做用户鉴权。这意味着一旦Odoo把预览URL返回给前端任何人都能用这个URL直接访问文档内容除非后端主动做限制。我的通行做法是预览URL中携带token参数token由Odoo生成并存储设置过期时间。预览服务在返回文件前先校验token是否存在、是否过期、对应的附件是否有效。这样可以做到链接仅在有效期内可访问过期即失效即使被转发出去对方也拿不到内容。这里有一个细节值得注意token的过期时间不宜太长。十分钟是一个比较合理的默认值能覆盖大多数用户从点击到看完的周期。太短了用户刷新一下就失效太长了又容易泄露后被利用。6.3 恶意文件与日志审计预览服务天天要处理用户上传的Office文档而这些文档可能是来源不可控的外部文件。如果某个文档携带了恶意宏转换进程在解析时万一触发了宏执行内网就直接暴露了。加固措施至少包括四条转换进程以低权限用户运行禁止写入用户目录上传附件做类型白名单校验关闭转换内核的宏执行选项对超大或结构异常的文档直接拒绝转换。尤其要注意最后一条很多恶意样本就是靠畸形文件结构来触发解析器漏洞的。日志审计同样重要。预览是高频操作日志量不小但至少需要记录三件事谁在什么时间预览了哪个附件、预览结果是成功还是失败、预览服务的响应耗时是多少。有一次客户投诉说“我明明没下载数据怎么泄露了”一查日志发现是他的预览链接被内部人员转发给了外部的人。没有日志这种问题根本说不清责任。最后分享一个我个人的体会做Office预览功能最忌讳一上来就追求“在线编辑”。大多数用户真正要的就是“快速、安全地看内容”。先把只读预览做到稳定、做到秒开再考虑放开编辑权限这两件事的优先级和投入完全是两回事。另外如果你正在做GoodERP这类二次开发项目一定记得把“文件名编码规则”和“预览URL鉴权”写进实施手册。我几乎每个项目都在这两个地方返过工提前写好能帮你少熬几个夜。
返回列表