在处理 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 文档添加规范的骑缝章,适用于合同、协议等重要文档的电子化处理场景。实际应用中可根据具体业务需求调整参数和逻辑。