You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP使用Base64解码打印PDF时输出原始字符串而非正常PDF问题

问题原因
  • 9100端口是网络打印机的RAW打印端口,默认仅接收打印机原生支持的页面描述语言(如PCL、PostScript、标签机的ZPL等),直接发送PDF二进制流时,只有自带PDF直解模块的高端商用打印机能识别渲染,绝大多数普通打印机会把收到的二进制数据当纯文本输出,就会出现打印PDF源码、乱码的现象。
  • 代码中调用printer('', 9100, $base64)时打印机IP参数传空,开发阶段连接本地/共享打印机时这段socket逻辑本身就无法正常工作。
  • 写PDF文件时用了w文本模式,在Windows等系统下会自动转义换行符,可能导致生成的PDF文件本身损坏。
  • 用exec("rm -rf")删除临时文件存在命令注入风险,且没有必要调用系统命令删文件。
修复方案

根据你的使用场景选以下任意一种方案即可:

方案1:调用系统打印服务(兼容性最高,支持所有打印机)

废弃直接socket发流的逻辑,把生成的PDF交给操作系统的打印队列处理,由系统完成PDF渲染和打印机适配,这是最稳定的通用方案。
不同系统的实现逻辑:

  • Linux(CUPS打印服务):用lp命令提交打印任务
  • Windows:可以调用系统print命令,或借助SumatraPDF等轻量工具实现静默打印
    替换原有socket发送部分的代码示例:
// 写入文件时改成wb二进制模式,避免PDF损坏
$pdf = fopen($docname, 'wb');
fwrite($pdf, $pdf_decoded);
fclose($pdf);

// Linux CUPS打印示例,$printer参数传CUPS中配置的打印机名称
$escapedDoc = escapeshellarg($docname);
$escapedPrinter = escapeshellarg($printer);
exec("lp -d {$escapedPrinter} {$escapedDoc}", $output, $returnVar);

if ($returnVar === 0) {
    echo "Successfully printed";
    unlink($docname); // 用PHP原生函数删文件,避免命令注入
} else {
    echo "Print failed, error code: " . $returnVar;
    unlink($docname);
}

注意:运行PHP的进程用户(如www-data、apache)需要加入打印用户组,拥有CUPS操作权限。

方案2:必须走9100网络端口打印的场景

如果不能依赖系统打印服务,必须直连网络打印机的9100端口,需要先把PDF转换成对应打印机支持的页面描述语言再发送:

  1. 服务器安装Ghostscript工具
  2. 生成临时PDF后,调用Ghostscript将PDF转换为打印机兼容的PCL/PostScript格式,转换命令示例(转PostScript):
gs -dNOPAUSE -dBATCH -sDEVICE=ps2write -sOutputFile=print_data.ps 你的临时PDF路径

如果目标打印机支持PCL,可将sDEVICE参数替换为对应PCL版本的驱动(如ljet4对应PCL5e)
3. 读取转换后的print_data.ps文件内容,通过socket发送到打印机9100端口即可。

方案3:打印机支持PDF直打场景

如果使用的是明确标注支持「PDF Direct Print」功能的高端商用打印机,不需要转格式,但需要在发送PDF流前,先发送对应厂商规定的控制指令,将打印机切换到PDF解析模式,具体指令需要查阅对应打印机型号的开发手册,普通消费级打印机无此功能,无需尝试。

额外优化建议
  • 用fsockopen代替pfsockopen,打印是一次性任务,不需要持久化连接,避免连接残留。
  • 所有文件写入操作如果是二进制内容,都用wb模式打开,避免跨平台兼容问题。
  • 临时文件删除统一用PHP原生unlink()函数,不要拼接shell命令执行,防范命令注入风险。

内容的提问来源于stack exchange,提问作者Joossieπ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 15:36:21