本文目录导读:

我来为您介绍PHP项目中批量添加PDF页码的几种方法:
使用FPDI + TCPDF(推荐)
<?php
require_once('tcpdf/tcpdf.php');
require_once('fpdi/fpdi.php');
class PDFMerger extends FPDI {
function addPageNumbers($sourceFile, $outputFile) {
// 获取原PDF页数
$pageCount = $this->setSourceFile($sourceFile);
// 遍历每一页
for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) {
$templateId = $this->importPage($pageNo);
$size = $this->getTemplateSize($templateId);
// 创建新页面
$this->AddPage($size['orientation'], array($size['width'], $size['height']));
$this->useTemplate($templateId);
// 设置页码样式
$this->SetFont('helvetica', 'B', 10);
$this->SetTextColor(0, 0, 0);
// 在页面底部添加页码
$pageNumText = "第 {$pageNo} 页 / 共 {$pageCount} 页";
$this->SetY(-20);
$this->SetX(0);
$this->Cell(0, 10, $pageNumText, 0, 0, 'C');
}
// 输出文件
$this->Output($outputFile, 'F');
}
// 批量处理PDF文件
function batchAddPageNumbers($inputDir, $outputDir) {
// 创建输出目录
if (!is_dir($outputDir)) {
mkdir($outputDir, 0777, true);
}
// 扫描PDF文件
$files = glob($inputDir . '/*.pdf');
foreach ($files as $file) {
$filename = basename($file);
$outputFile = $outputDir . '/numbered_' . $filename;
echo "处理: {$filename}\n";
// 重置FPDI
$this->setSourceFile($file);
$this->addPageNumbers($file, $outputFile);
echo "已完成: {$outputFile}\n";
}
}
}
// 使用示例
$pdf = new PDFMerger();
$pdf->batchAddPageNumbers('./input', './output');
使用MPDF库
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Mpdf\Mpdf;
class BatchPDFPageNumber {
private $mpdf;
public function __construct() {
$this->mpdf = new Mpdf([
'tempDir' => __DIR__ . '/tmp'
]);
}
public function addPageNumbers($inputFile, $outputFile) {
// 读取源PDF
$pageCount = $this->mpdf->setSourceFile($inputFile);
for ($i = 1; $i <= $pageCount; $i++) {
// 导入页面
$templateId = $this->mpdf->importPage($i);
$this->mpdf->AddPage();
$this->mpdf->useTemplate($templateId);
// 添加页码
$this->mpdf->SetY(-15);
$this->mpdf->SetFont('Arial', 'B', 9);
$this->mpdf->Cell(0, 10, "Page {$i} of {$pageCount}", 0, 0, 'C');
}
// 保存输出
$this->mpdf->Output($outputFile, 'F');
}
public function batchProcess($inputDir, $outputDir) {
if (!is_dir($outputDir)) {
mkdir($outputDir, 0777, true);
}
$pdfFiles = glob($inputDir . '/*.pdf');
foreach ($pdfFiles as $pdfFile) {
$filename = basename($pdfFile);
$outputPath = $outputDir . '/numbered_' . $filename;
echo "处理: {$filename}...\n";
// 重置MPDF实例
$this->mpdf = new Mpdf(['tempDir' => __DIR__ . '/tmp']);
$this->addPageNumbers($pdfFile, $outputPath);
echo "完成: {$outputPath}\n";
}
}
}
// 使用示例
$processor = new BatchPDFPageNumber();
$processor->batchProcess('./input_pdfs', './output_pdfs');
使用命令行工具(适用于Bulk处理)
<?php
class PDFBatchProcessor {
// 使用Ghostscript添加页码
public function gsAddPageNumbers($inputDir, $outputDir, $prefix = 'numbered_') {
if (!is_dir($outputDir)) {
mkdir($outputDir, 0777, true);
}
$files = glob($inputDir . '/*.pdf');
foreach ($files as $file) {
$filename = basename($file, '.pdf');
$outputFile = $outputDir . '/' . $prefix . $filename . '.pdf';
// Ghostscript命令添加页码
$command = "gs -q -dBATCH -dNOPAUSE -sDEVICE=pdfwrite ";
$command .= "-sOutputFile={$outputFile} ";
$command .= "-c \"<< /PageNumFont /Helvetica /PageNumSize 10 ";
$command .= "/PageNumPos (bottom center) /StartPage 1 >> setpagedevice\" ";
$command .= "-f {$file}";
exec($command, $output, $returnCode);
if ($returnCode === 0) {
echo "成功处理: {$filename}\n";
} else {
echo "处理失败: {$filename}\n";
}
}
}
// 使用PDFtk添加页码(需要安装PDFtk)
public function pdftkAddPageNumbers($inputDir, $outputDir) {
if (!is_dir($outputDir)) {
mkdir($outputDir, 0777, true);
}
$files = glob($inputDir . '/*.pdf');
$stampFile = __DIR__ . '/page_number_stamp.pdf';
// 创建页码水印PDF(需要提前创建)
foreach ($files as $file) {
$filename = basename($file);
$outputFile = $outputDir . '/numbered_' . $filename;
// 使用PDFtk添加水印
$command = "pdftk {$file} stamp {$stampFile} output {$outputFile}";
exec($command, $output, $returnCode);
if ($returnCode === 0) {
echo "处理完成: {$filename}\n";
}
}
}
}
// 使用示例
$processor = new PDFBatchProcessor();
$processor->gsAddPageNumbers('./input', './output');
基于目录的批量处理类
<?php
class AdvancedBatchPDFNumberer {
private $options = [
'font' => 'helvetica',
'size' => 10,
'style' => 'B',
'position' => 'bottom', // bottom/top
'align' => 'center', // left/center/right
'format' => '第 {current} 页 / 共 {total} 页',
'margin_bottom' => 20
];
public function __construct($options = []) {
$this->options = array_merge($this->options, $options);
}
public function processDirectory($inputDir, $outputDir, $recursive = false) {
if (!is_dir($outputDir)) {
mkdir($outputDir, 0777, true);
}
$files = $recursive ?
$this->getAllPDFFiles($inputDir) :
glob($inputDir . '/*.pdf');
$results = [];
foreach ($files as $file) {
$relativePath = str_replace($inputDir, '', $file);
$outputPath = $outputDir . '/' . ltrim($relativePath, '/');
// 创建输出目录
$outputDirPath = dirname($outputPath);
if (!is_dir($outputDirPath)) {
mkdir($outputDirPath, 0777, true);
}
try {
$this->addPageNumbersToFile($file, $outputPath);
$results[] = [
'file' => $file,
'status' => 'success',
'output' => $outputPath
];
} catch (Exception $e) {
$results[] = [
'file' => $file,
'status' => 'error',
'message' => $e->getMessage()
];
}
}
return $results;
}
private function getAllPDFFiles($dir) {
$files = [];
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir)
);
foreach ($iterator as $file) {
if ($file->isFile() && $file->getExtension() === 'pdf') {
$files[] = $file->getPathname();
}
}
return $files;
}
private function addPageNumbersToFile($inputFile, $outputFile) {
// 使用FPDI实现(需要提前安装)
require_once('fpdi/fpdi.php');
$pdf = new FPDI();
$pageCount = $pdf->setSourceFile($inputFile);
for ($page = 1; $page <= $pageCount; $page++) {
$templateId = $pdf->importPage($page);
$size = $pdf->getTemplateSize($templateId);
$pdf->AddPage($size['orientation'], [$size['width'], $size['height']]);
$pdf->useTemplate($templateId);
// 页码文本
$pageText = str_replace(
['{current}', '{total}'],
[$page, $pageCount],
$this->options['format']
);
// 设置字体
$pdf->SetFont(
$this->options['font'],
$this->options['style'],
$this->options['size']
);
// 计算位置
$y = ($this->options['position'] === 'bottom') ?
($size['height'] - $this->options['margin_bottom']) :
$this->options['margin_bottom'];
$pdf->SetY($y);
$pdf->SetX(0);
$pdf->Cell(0, 10, $pageText, 0, 0, $this->options['align']);
}
$pdf->Output($outputFile, 'F');
}
}
// 使用示例
$numberer = new AdvancedBatchPDFNumberer([
'format' => '第 {current} 页',
'position' => 'bottom',
'align' => 'center'
]);
$results = $numberer->processDirectory('./input', './output', true);
// 显示结果
foreach ($results as $result) {
if ($result['status'] === 'success') {
echo "✓ {$result['file']} -> {$result['output']}\n";
} else {
echo "✗ {$result['file']}: {$result['message']}\n";
}
}
安装依赖
使用Composer安装必要的库:
# FPDI + TCPDF composer require setasign/fpdi composer require tecnickcom/tcpdf # 或者使用MPDF composer require mpdf/mpdf # 或者安装系统工具 # Ubuntu/Debian sudo apt-get install pdftk ghostscript # macOS brew install pdftk gs
推荐方案
- 小规模批量处理(<100个文件):使用FPDI + TCPDF
- 大规模批量处理(>1000个文件):使用Ghostscript命令行
- 需要复杂排版:使用MPDF库
选择最适合您项目需求的方案即可。