如何使用PHP实现PDF单页排版展示多张幻灯片内容
PHP实现PDF多页幻灯片拼版方案
完全可以实现,优先选择保留原PDF矢量画质的方案,不建议默认用ImageMagick/GD转位图拼接——后者会导致文字发虚、文件体积暴涨,仅适合扫描版PDF使用。
首选方案:基于FPDI库原生拼版(逻辑最灵活、画质无损)
这是PHP生态下最稳定的实现方式,不需要调用额外系统命令,直接操作PDF内容结构,排版参数可完全自定义:
- 前置依赖:通过Composer安装
setasign/fpdi组件,执行安装命令:composer require setasign/fpdi - 实现逻辑:按设定的每页幻灯片数量(比如4张对应2行2列),逐页导入原PDF内容,等比缩放后放到新页面的对应坐标位置即可,可直接运行的代码如下:
<?php require __DIR__ . '/vendor/autoload.php'; use setasign\Fpdi\Fpdi; // 配置项 $sourcePdfPath = 'original_10page_slides.pdf'; // 原PDF路径 $outputPdfPath = 'merged_4up_slides.pdf'; // 输出PDF路径 $slidesPerPage = 4; // 每页放置的幻灯片数量 $columns = 2; // 排版列数 $rows = 2; // 排版行数 $pageMargin = 10; // 页边距 单位mm $pageSize = 'A4'; // 输出页面尺寸 $pdf = new Fpdi(); $totalSourcePages = $pdf->setSourceFile($sourcePdfPath); // 计算单个幻灯片占位尺寸 $pageWidth = $pdf->GetPageWidth($pageSize); $pageHeight = $pdf->GetPageHeight($pageSize); $cellWidth = ($pageWidth - $pageMargin * ($columns + 1)) / $columns; $cellHeight = ($pageHeight - $pageMargin * ($rows + 1)) / $rows; for ($pageNo = 1; $pageNo <= $totalSourcePages; $pageNo++) { // 每排满指定数量幻灯片,新建一个输出页 if (($pageNo - 1) % $slidesPerPage === 0) { $pdf->AddPage('P', $pageSize); } // 计算当前幻灯片在输出页的位置 $positionInCurrentPage = ($pageNo - 1) % $slidesPerPage; $currentCol = $positionInCurrentPage % $columns; $currentRow = floor($positionInCurrentPage / $columns); $x = $pageMargin + $currentCol * ($cellWidth + $pageMargin); $y = $pageMargin + $currentRow * ($cellHeight + $pageMargin); // 导入原幻灯片页面,等比缩放适配占位区域 $templateId = $pdf->importPage($pageNo); $pdf->useTemplate($templateId, $x, $y, $cellWidth, $cellHeight, true); } $pdf->Output($outputPdfPath, 'F'); - 上述代码针对10页原PDF的场景,会自动生成3页输出:第1页放1-4页、第2页放5-8页、第3页放9-10页,和需求完全匹配。如果要改成每页放2张、6张、9张,只需要调整对应的
$slidesPerPage、$columns、$rows参数即可。
备选方案:调用Ghostscript命令行拼版
如果不想安装Composer依赖,服务器已装Ghostscript的情况下,可以通过PHP的shell_exec()调用gs命令实现拼版,同样是无损矢量拼接:
- 注意点:调用时必须用
escapeshellarg()处理文件路径,避免命令注入风险;需要手写少量PostScript指令控制页面缩放、平移,阻止原页面自动换页,等4张幻灯片排布完成后再触发新页生成。 - 适合固定排版规则的场景,灵活度比FPDI方案差,排版参数调整需要修改PostScript代码,调试成本稍高。
不推荐的方案:ImageMagick/GD位图拼接
这类方案的逻辑是先把原PDF每页转成高清位图,再把多张位图绘制到同一张画布上最后导出PDF,存在几个明显问题:
- 原PDF的矢量文字、线条会变成位图,放大后发虚
- 输出文件体积是原生拼版方案的5-10倍
- 渲染速度慢,大页数PDF处理耗时长
仅当原PDF是扫描版、本身全是位图内容时,才考虑用这个方案。
内容的提问来源于stack exchange,提问作者Alexandre
相关产品推荐
相关产品推荐

