TCPDF页眉显示数据库Blob图片失败问题排查
TCPDF页眉显示数据库Blob图片失败问题排查
需要在TCPDF生成的文档页眉中,显示根据所选公司从数据库获取的Blob图片。测试了多种方案,其中两种在页眉外可正常运行,但在页眉内要么导致页面损坏,要么图片不可见,具体代码如下:
$stmt_antet = $conn->prepare("SELECT antet FROM societati WHERE id_societate = ?"); $stmt_antet->bind_param("s", $id_societate_raport); if (!$stmt_antet->execute()) { echo mysqli_errno($conn); } else { $result_antet = $stmt_antet->get_result(); $row_antet = $result_antet->fetch_assoc(); $antet = $row_antet['antet']; } require_once('tcpdf/examples/tcpdf_include.php'); class MYPDF extends TCPDF { public function Header() { // 方案1:页面损坏 $imgdata_m = base64_decode($antet); $this->Image('@'.$imgdata_m, 25, 35, 160, 24, 'PNG', '', 'T', false, 300, '', false, false, 0, false, false, false); // 方案2:页面损坏,且在页眉外也无法运行 $antet_encoded = "data:image/png;base64,".$antet; $this->tcpdf->Image("@".$antet_encoded, 25, 35, 160, 24, 'PNG', '', 'T', false, 300, '', false, false, 0, false, false, false); // 方案3:报错:TCPDF ERROR: [Image] Unable to get the size of the image $img_base64_encoded = 'data:image/jpg;base64,'.$antet; $imageContent = file_get_contents($img_base64_encoded); $path = tempnam(sys_get_temp_dir(), 'prefix'); file_put_contents($path, $imageContent); $img = '<img src="' . $path . '">'; $this->writeHTML($img, 25, 35, 160, 24, 'PNG', '', 'T', false, 300, '', false, false, 0, false, false, false); } } // 页眉外可正常运行的方案1 $imgdata_m = base64_decode($antet); $pdf->Image('@'.$imgdata_m, 25, 35, 160, 24, 'PNG', '', 'T', false, 300, '', false, false, 0, false, false, false); // 页眉外可正常运行的方案2 $img_base64_encoded = 'data:image/jpg;base64,'.$antet; $imageContent = file_get_contents($img_base64_encoded); $path = tempnam(sys_get_temp_dir(), 'prefix'); file_put_contents($path, $imageContent); $img = '<img src="' . $path . '">'; $pdf->writeHTML($img, 25, 35, 160, 24, 'PNG', '', 'T', false, 300, '', false, false, 0, false, false, false);
核心问题分析
- 变量作用域限制:
$antet是在MYPDF类外部定义的变量,类的Header()方法默认无法直接访问外部变量,导致获取的图片数据为空或无效,这是页面损坏的核心原因。 - 错误的方法调用:方案2中使用
$this->tcpdf->Image是错误的——MYPDF继承自TCPDF,直接调用$this->Image即可,多余的tcpdf属性调用会触发对象不存在的错误。 - writeHTML参数错误:方案3中
writeHTML的参数用法错误,该方法不支持直接传入位置坐标参数,且临时文件路径在HTML中无法被TCPDF正确解析。
解决方案
方案1:通过构造函数传递图片数据(推荐)
修改MYPDF类,在实例化时传入$antet并存储为类属性,供Header方法调用:
class MYPDF extends TCPDF { private $headerImageData; public function __construct($imageData, $orientation='P', $unit='mm', $format='A4', $unicode=true, $encoding='UTF-8', $diskcache=false, $pdfa=false) { parent::__construct($orientation, $unit, $format, $unicode, $encoding, $diskcache, $pdfa); $this->headerImageData = $imageData; } public function Header() { if ($this->headerImageData) { $imgdata = base64_decode($this->headerImageData); $this->Image('@'.$imgdata, 25, 35, 160, 24, 'PNG', '', 'T', false, 300, '', false, false, 0, false, false, false); } } } // 实例化时传入图片数据 $pdf = new MYPDF($antet);
方案2:声明全局变量(快速临时方案)
在Header方法内声明$antet为全局变量,使其可以访问外部定义的变量:
class MYPDF extends TCPDF { public function Header() { global $antet; if ($antet) { $imgdata_m = base64_decode($antet); $this->Image('@'.$imgdata_m, 25, 35, 160, 24, 'PNG', '', 'T', false, 300, '', false, false, 0, false, false, false); } } }
方案3:修正writeHTML使用方式
如果要使用writeHTML,需先设置坐标再调用方法,并确保临时文件路径有效:
class MYPDF extends TCPDF { private $headerImagePath; public function __construct($imagePath, $orientation='P', $unit='mm', $format='A4', $unicode=true, $encoding='UTF-8', $diskcache=false, $pdfa=false) { parent::__construct($orientation, $unit, $format, $unicode, $encoding, $diskcache, $pdfa); $this->headerImagePath = $imagePath; } public function Header() { if ($this->headerImagePath) { $img = '<img src="' . $this->headerImagePath . '" width="160" height="24">'; $this->SetXY(25, 35); // 先设置坐标 $this->writeHTML($img, true, false, true, false, ''); } } } // 提前处理临时文件并传入路径 $img_base64_encoded = 'data:image/jpg;base64,'.$antet; $imageContent = file_get_contents($img_base64_encoded); $path = tempnam(sys_get_temp_dir(), 'prefix'); file_put_contents($path, $imageContent); $pdf = new MYPDF($path); // 生成文档后记得清理临时文件 // $pdf->Output(...); // unlink($path);
内容的提问来源于stack exchange,提问作者Sorina
相关产品推荐
相关产品推荐

