Laravel 中使用 FPDI 实现 PDF 骑缝章功能
在处理 PDF 文档时,我们经常需要为多页文档添加骑缝章,确保文档的完整性和严肃性。本文将介绍如何在 Laravel 框架中使用 FPDI 扩展库实现这一功能,通过分割印章图片并按页添加的方式,生成规范的骑缝章效果。
一、实现思路
骑缝章的核心原理是将一个完整的印章图片分割成与 PDF 页数相同的份数,然后在每一页的边缘位置添加对应的分割部分,拼接成完整的印章效果。实现步骤如下:
1、使用 FPDI 读取原始 PDF 文档并获取页数
2、将印章图片按 PDF 页数进行均等分割
3、循环处理每一页 PDF,添加对应的分割印章
4、重新生成带骑缝章的 PDF 文档
二、环境准备
首先需要安装 FPDI 相关依赖,通过 Composer 执行以下命令:
composer require setasign/fpdi-fpdf
该扩展库基于 FPDF,提供了 PDF 文档的读取和编辑功能,非常适合处理 PDF 盖章场景。
三、完整实现代码
以下是实现骑缝章功能的核心代码,包含 PDF 处理和图片分割逻辑:
/*** 为PDF添加骑缝章* @param string $file PDF文件路径* @param string $acrossPageSeal 骑缝章图片路径* @return string 处理后的文件路径*/
public function addSealToPDF($file, $acrossPageSeal)
{try {// 初始化FPDI对象$pdf = new Fpdi();// 去除默认页眉页脚(如横线等)$pdf->setPrintHeader(false);$pdf->setPrintFooter(false);$pdf->setFontSubsetting(false);// 读取PDF文件并获取总页数$page_num = $pdf->setSourceFile(public_path($file));// 仅对多页PDF添加骑缝章if ($page_num > 1 && !empty($acrossPageSeal)) {// 分割印章图片为与页数相同的份数$to_imgs = self::cuttingImg(public_path($acrossPageSeal), $page_num, 'to');// 循环处理每一页for ($i = 0; $i < $page_num; $i++) {// 添加新页面$pdf->AddPage();// 导入当前页模板$tplId = $pdf->importPage($i + 1);$pdf->useTemplate($tplId);// 在指定位置添加分割后的印章// 参数说明:图片路径、X坐标、Y坐标、宽度、高度、格式$pdf->Image($to_imgs[$i], 195, 110, 15, '', 'png');}// 输出并覆盖原文件(F模式表示保存到本地文件)$pdf->Output(public_path($file), 'F');}} catch (\Exception $exception) {// 异常处理:如果原文件存在则返回原文件if (Storage::exists($file)) {return $file;}}return $file;
}/*** 分割图片为指定份数* @param string $imgPath 原始图片路径* @param int $num 分割份数* @param string $dir 保存目录* @return array 分割后的图片路径数组*/
private function cuttingImg($imgPath, $num, $dir)
{// 确保保存目录存在$saveDir = public_path($dir);if (!file_exists($saveDir)) {mkdir($saveDir, 0755, true);}// 获取图片信息list($width, $height, $type) = getimagesize($imgPath);$ext = image_type_to_extension($type, false);// 根据图片类型创建资源switch ($type) {case IMAGETYPE_PNG:$source = imagecreatefrompng($imgPath);break;case IMAGETYPE_JPEG:$source = imagecreatefromjpeg($imgPath);break;default:throw new \Exception("不支持的图片格式");}$result = [];// 计算每一份的宽度(横向分割)$partWidth = ceil($width / $num);for ($i = 0; $i < $num; $i++) {// 创建新图片资源$newImg = imagecreatetruecolor($partWidth, $height);// 保留PNG透明度if ($type == IMAGETYPE_PNG) {imagesavealpha($newImg, true);$transColor = imagecolorallocatealpha($newImg, 0, 0, 0, 127);imagefill($newImg, 0, 0, $transColor);}// 复制图片部分区域imagecopy($newImg, $source, 0, 0, $i * $partWidth, 0, $partWidth, $height);// 保存分割后的图片$savePath = $saveDir . '/' . uniqid() . '.' . $ext;switch ($type) {case IMAGETYPE_PNG:imagepng($newImg, $savePath);break;case IMAGETYPE_JPEG:imagejpeg($newImg, $savePath);break;}$result[] = $savePath;imagedestroy($newImg);}imagedestroy($source);return $result;
}
四、代码解析
1、PDF 处理核心逻辑:
- 使用 Fpdi 类初始化 PDF 处理对象
- 通过 setSourceFile 方法读取 PDF 并获取页数
- 循环处理每一页时,先导入原页面模板,再添加对应分割的印章图片
- 用 Output 方法以覆盖模式保存处理后的 PDF
2、图片分割关键步骤:
- 根据 PDF 页数计算每部分印章的宽度
- 使用 GD 库函数进行图片分割处理
- 针对 PNG 图片保留透明度,确保盖章效果自然
- 分割后的图片临时保存,供 PDF 处理使用
3、坐标与尺寸设置:
- Image 方法中的参数 195, 110, 15 分别代表 X 坐标、Y 坐标和宽度
- 实际使用中需根据 PDF 尺寸和印章大小调整,建议通过多次测试确定最佳位置
通过以上实现,我们可以在 Laravel 项目中快速为 PDF 文档添加规范的骑缝章,适用于合同、协议等重要文档的电子化处理场景。实际应用中可根据具体业务需求调整参数和逻辑。