Ghostscript 8.70降级PDF至1.4报错,求优化命令或替代方案
- 在LAMP栈(PHP 7.3)中实现PDF文档按需加水印功能
- 网页应用将多版本PDF存储于MySQL表中
- 采用基于FPDF的PDF加水印方案
- 曾遇到PDF版本兼容问题,因此引入Ghostscript将所有文档降级至PDF 1.4版本
当前使用的Ghostscript命令
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dNOPAUSE -dQUIET -dBATCH -sOutputFile=/tmp/63d319f2d1018.pdf /tmp/63d319f2cfb51.pdf
问题文档报错详情
- 多数文档可正常完成加水印流程,但有一份文档执行Ghostscript时失败
- 原始PDF可在浏览器和Acrobat Reader中正常渲染
- 报错信息:
Error: /rangecheck in --makepattern-- Operand stack: --dict:11/20(L)-- --dict:14/23(L)-- --dict:14/23(L)-- --nostringval-- false --dict:14/15(L)-- --nostringval-- Execution stack: %interp_exit .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- --nostringval-- false 1 %stopped_push 1862 1 3 %oparray_pop 1861 1 3 %oparray_pop 1845 1 3 %oparray_pop --nostringval-- --nostringval-- 24 1 34 --nostringval-- %for_pos_int_continue --nostringval-- --nostringval-- false 1 %stopped_push --nostringval-- --nostringval-- --nostringval-- %array_continue --nostringval-- false 1 %stopped_push --nostringval-- %loop_continue --nostringval-- --nostringval-- --nostringval-- --nostringval-- 1811 4 10 %oparray_pop --nostringval-- Dictionary stack: --dict:1150/1684(ro)(G)-- --dict:1/20(G)-- --dict:76/200(L)-- --dict:76/200(L)-- --dict:106/127(ro)(G)-- --dict:286/300(ro)(G)-- --dict:22/25(L)-- --dict:4/6(L)-- --dict:25/40(L)-- --dict:3/5(L)-- Current allocation mode is local Last OS error: 2 GPL Ghostscript 8.70: Unrecoverable error, exit code 1 GPL Ghostscript 8.70: ERROR: A pdfmark destination page 34 points beyond the last page 22.
解决方案建议
优化Ghostscript命令及版本
- 升级Ghostscript版本:当前使用的8.70版本过于陈旧,对新PDF特性支持不足且存在已知兼容性bug,升级至最新稳定版(如10.x系列)可大幅减少这类错误。
- 添加容错参数:针对报错中的pdfmark页码引用错误,可在命令中加入容错参数:
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dNOPAUSE -dQUIET -dBATCH -dHandleBadReferences=true -dPDFSTOPONERROR=false -sOutputFile=/tmp/output.pdf /tmp/input.pdf
-dHandleBadReferences=true:忽略无效的页面引用-dPDFSTOPONERROR=false:遇到非致命错误时继续处理,而非直接终止
替代实现方案
- 使用TCPDF替代FPDF:TCPDF是FPDF的升级版,支持更高版本的PDF,无需预先降级PDF,可直接处理大多数现代PDF文档并添加水印,减少Ghostscript依赖。
- 使用Imagick扩展:借助PHP Imagick扩展直接给PDF加水印,底层依赖Ghostscript但兼容性更强,示例代码:
$imagick = new Imagick(); $imagick->readImage('/path/to/input.pdf'); $watermark = new Imagick('/path/to/watermark.png'); $imagick->compositeImage($watermark, Imagick::COMPOSITE_OVER, 100, 100); $imagick->writeImage('/path/to/output.pdf'); $imagick->clear(); $imagick->destroy();
- 改用mPDF库:mPDF支持直接加载PDF并添加水印,对PDF版本兼容性较好,无需额外依赖Ghostscript预处理。
内容的提问来源于stack exchange,提问作者badams

