
在日常工作中,我们有时会遇到需要打印超大尺寸PDF文档(例如工程图纸、海报或缝纫图案)的情况。这些文档通常设计为单页,但实际打印时需要将其拆分成多张标准尺寸的纸张(如A4或Letter),再进行拼接。传统的解决方案可能包括使用ImageMagick将PDF转换为图像,然后裁剪并重新组合,但这不仅效率低下,还可能导致图像质量损失。本教程将介绍一种更为优雅和高效的方法,利用PHP的FPDF和FPDI库直接对PDF内容进行操作,实现高质量的页面分片。
FPDI(FPDF_TPL, FPDF_PARSER, FPDF_CORE)是一个基于FPDF的扩展,它允许我们导入现有的PDF页面作为模板,然后在新的PDF文档中进行操作。其核心思想是:
这种方法避免了图像转换的中间步骤,直接操作PDF矢量数据,因此能够保持原始文档的清晰度和质量。
在开始之前,请确保您的PHP环境中已安装并配置好FPDF和FPDI库。您可以通过Composer进行安装:
立即学习“PHP免费学习笔记(深入)”;
composer require setasign/fpdf composer require setasign/fpdi
如果您的项目没有使用Composer,您可以手动下载库文件并将其包含在项目中。
以下是一个详细的PHP代码示例,演示如何将一个24英寸高、96英寸宽的单页PDF分割成多个Letter尺寸(8.5英寸宽、11英寸高)的页面。
<?php
require_once('vendor/autoload.php'); // 如果使用Composer,请确保路径正确
use setasign\Fpdi\Fpdi;
/**
* 将大型PDF页面分割成多个标准尺寸页面
*
* @param string $sourcePdfPath 源PDF文件路径
* @param string $outputPdfPath 输出PDF文件路径
* @param float $targetPageWidthInch 目标页面宽度(英寸)
* @param float $targetPageHeightInch 目标页面高度(英寸)
* @return bool 操作成功返回true,否则返回false
*/
function tileLargePdf(string $sourcePdfPath, string $outputPdfPath, float $targetPageWidthInch, float $targetPageHeightInch): bool
{
if (!file_exists($sourcePdfPath)) {
echo "错误:源PDF文件不存在。\n";
return false;
}
// FPDF默认单位是毫米,所以需要将英寸转换为毫米
$inchToMm = 25.4;
$targetPageWidthMm = $targetPageWidthInch * $inchToMm;
$targetPageHeightMm = $targetPageHeightInch * $inchToMm;
$pdf = new Fpdi();
try {
// 设置源文件并导入第一页作为模板
$pageCount = $pdf->setSourceFile($sourcePdfPath);
if ($pageCount < 1) {
echo "错误:源PDF文件不包含任何页面。\n";
return false;
}
$templateId = $pdf->importPage(1); // 导入源PDF的第一页
// 获取源页面的原始尺寸(FPDI返回的是点,需要转换为毫米)
// 1点 = 1/72英寸,1英寸 = 25.4毫米
$templateSize = $pdf->getTemplateSize($templateId);
$sourceWidthPt = $templateSize['width'];
$sourceHeightPt = $templateSize['height'];
$sourceWidthMm = $sourceWidthPt * ($inchToMm / 72);
$sourceHeightMm = $sourceHeightPt * ($inchToMm / 72);
echo "源PDF尺寸:宽度 " . round($sourceWidthMm, 2) . "mm, 高度 " . round($sourceHeightMm, 2) . "mm\n";
echo "目标页面尺寸:宽度 " . round($targetPageWidthMm, 2) . "mm, 高度 " . round($targetPageHeightMm, 2) . "mm\n";
// 计算需要多少行和多少列才能覆盖整个源页面
$cols = ceil($sourceWidthMm / $targetPageWidthMm);
$rows = ceil($sourceHeightMm / $targetPageHeightMm);
echo "将生成 " . $rows . " 行," . $cols . " 列,总计 " . ($rows * $cols) . " 页。\n";
// 循环生成每一片页面
for ($row = 0; $row < $rows; $row++) {
for ($col = 0; $col < $cols; $col++) {
// 添加一个新页面,尺寸为目标页面尺寸
$pdf->AddPage('P', [$targetPageWidthMm, $targetPageHeightMm]);
// 计算当前分片在源页面上的起始坐标(毫米)
// 我们需要将源模板向左上方移动,以便当前分片区域对齐新页面的左上角
$offsetX = -$col * $targetPageWidthMm;
$offsetY = -$row * $targetPageHeightMm;
// 将源模板放置到新页面上
// useTemplate的参数:模板ID, X坐标, Y坐标, 宽度, 高度
// 这里的宽度和高度应是源模板的原始尺寸,以保持其比例和分辨率
$pdf->useTemplate($templateId, $offsetX, $offsetY, $sourceWidthMm, $sourceHeightMm);
}
}
// 输出PDF到文件
$pdf->Output($outputPdfPath, 'F');
echo "PDF分片成功,输出文件:{$outputPdfPath}\n";
return true;
} catch (Exception $e) {
echo "处理PDF时发生错误:" . $e->getMessage() . "\n";
return false;
}
}
// --- 使用示例 ---
$sourcePdf = 'large_pattern.pdf'; // 替换为您的源PDF文件路径
$outputPdf = 'tiled_pattern_output.pdf'; // 输出文件路径
$letterWidth = 8.5; // Letter纸张宽度(英寸)
$letterHeight = 11; // Letter纸张高度(英寸)
// 确保您的源PDF文件存在于脚本可访问的路径
// 您可以创建一个简单的测试PDF,例如一个24x96英寸的空白PDF,或者使用您实际的缝纫图案PDF。
// 如果没有,可以手动创建一个名为 large_pattern.pdf 的文件用于测试。
if (tileLargePdf($sourcePdf, $outputPdf, $letterWidth, $letterHeight)) {
echo "请检查 {$outputPdf} 文件。\n";
} else {
echo "PDF分片处理失败。\n";
}
?>如何运行此代码:
通过FPDI和FPDF的结合,我们能够以编程方式高效地将大型单页PDF文档分割成多个适合打印的标准尺寸页面。这种方法不仅避免了图像转换带来的质量损失,而且提供了高度的灵活性和自动化能力,特别适用于需要批量处理或集成到现有工作流中的场景。掌握这一技术,将使您在处理PDF文档时拥有更大的自主权和效率。
以上就是使用FPDI和FPDF在PHP中实现大型PDF页面分片打印教程的详细内容,更多请关注php中文网其它相关文章!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号