Laravel 审批页保存 PDF 批注:怎样避免覆盖别人的修改?

两个人先后打开同一份报价 PDF,各自加了批注。第一个人保存后,第二个人再保存,如果服务端只按文件 ID 覆盖原路径,第一个人的修改就可能丢失。浏览器里两次都提示成功,也不能证明最后留下了两份意见。
这个问题要在保存接口里处理。PDF 组件负责导出文档,Laravel 应用负责判断:上传的人是否有权限,以及他修改的还是不是当前版本。
打开时,文件和版本一起返回
审批页需要的不只是一条 PDF 下载地址。后端检查用户、审批任务与附件的关系之后,应把文件标识和本次打开的版本一起返回,例如:
{
"attachmentId": "quote-127",
"baseRevision": 4,
"fileUrl": "由应用签发的当前版本访问地址"
}
这是应用接口的设计示例,不是 ComPDF 的返回格式。baseRevision=4 表示用户接下来要修改的起点;文件换成第 5 版时,不能只更新地址却沿用第 4 版的状态。
真实文件地址应从自己的存储和授权流程取得,不要将上面的中文占位值直接填进 viewer。带时效的地址也不替代任务权限检查:用户在审批页能看到附件,不代表他拥有该附件所有历史版本的写权限。
接入 PDF 操作,但别把“导出”当作“归档”
如果需要在审批页查看和批注,可以按 ComPDF Web 接入指南部署组件,先打开一份有权处理的文件,再验证批注与导出路径。Laravel 可以返回页面和文件信息,PDF 的浏览器交互由前端组件完成,不是在 PHP 控制器里调用浏览器实例。
用户点保存时,从当前文档实例取出 PDF 数据,上传到 Laravel 的附件保存接口。ComPDF 的文档保存说明给出了导出数据及上传服务器的接法;身份验证、版本冲突和存储回执由应用补齐。
页面状态至少分为“正在导出、正在上传、已保存、保存失败或版本冲突”。取得 Blob 后还没有服务器保存结果,此时不能把审批页改成已完成。
保存接口,先比版本,再切换当前文件
前端随文件提交 attachmentId 和打开时的 baseRevision。不要用客户端传来的作者名、审批状态或下一版本号直接更新数据库。
后端可以按以下顺序组织:
- 用 Laravel Policy 检查当前用户是否能修改该任务与附件;校验上传文件大小及内容,放入隔离的临时位置。
- 开启数据库事务,锁定对应附件记录,读取当前修订号。版本检查必须与更新当前修订在同一原子操作中,不能检查完就放开锁再改。
- 比较提交的基础版本。如果当前已经是 5,而用户交来的基础版本仍是 4,返回版本冲突,不覆盖第 5 版。
- 版本一致时,建立新修订记录,将文件存入唯一、不可被旧任务覆盖的路径;存储成功后再更新当前修订及操作者。
- 提交成功后返回新版本信息;存储失败或数据库提交失败时,应回滚当前引用,并清理或单独回收孤立文件。
文件存储与数据库事务不是同一件事,回滚数据库不会自动删除已经上传的文件。采用哪种“暂存、提交、清理”方案要看本地磁盘或对象存储的条件,不能用一段事务代码就声称文件和记录天然一致。

图:应用保存流程示意,不是组件自动提供的版本管理。
冲突时,不能自动覆盖或拼成一份
接口可以用 HTTP 409 表示版本已变化,并返回当前修订号。页面提示“这份文件已有更新,请重新打开后核对”,保留用户当前的修改,提供另存本地副本或取消操作的选择。
不要把“重试”写成无条件覆盖。两份带批注的 PDF 并不适合靠拼接字节合并;是否合并注释,需要字段标识、坐标、文档版本和组件导入导出能力都能对应,还要解决同一意见被编辑或删除的问题。没有做过这些处理,就让用户重新核对,保留两个来源版本。
同样,保存副本和同意审批应分开。文件上传成功后,业务还可能需要检查意见、确认人和审批条件,不能直接进入下一节点。
上线前,双开页面走一遍
不用复杂压测就能先检查最容易丢修改的一条路径:
- A、B 两个页面都打开第 4 版,分别加上可区分的批注。
- A 保存,服务端生成第 5 版;重新打开第 5 版检查 A 的意见确实存在。
- B 保存,提交的仍应是基础版本 4,接口应拒绝覆盖并提示冲突。
- B 的页面保留未提交内容,不因失败就清空;A 的第 5 版保持不变。
- 换成无修改权限的用户,直接调用保存接口,后端仍应拒绝。
- 模拟上传或存储失败,检查当前版本没有指向缺失文件,也没有把审批状态提前标为完成。
这是一套可自行执行的接入与验收方法,不代表浏览器组件自动提供协同编辑或业务版本管理。先把“一人保存、另一人不丢修改”做对,再考虑自动保存、多人协作或注释合并。
选择 ComPDF 是为了解决 PDF 页面交互、批注和文件导出;把这些产物接成可靠审批,仍需要 Laravel 把权限、基础版本、存储和回执连起来。下次排查“批注怎么没了”时,先看导出的文件有没有意见,再看保存接口是否覆盖了别人的版本,两个问题就能分开定位。
本作品采用《CC 协议》,转载必须注明作者和本文链接
关于 LearnKu
推荐文章: