CodeIgniter3中使用FPDI合并PDF报错:页码超出可用范围
CodeIgniter3 + FPDI合并PDF报错:页码超出可用范围
在CodeIgniter3框架中使用FPDI合并多个PDF为单个文件时,执行代码行$tplIdx = $pdf->importPage($i);时出现错误:
Fpdi Error Message: Page number "3" out of available page range (1 - 2)
以下是原代码:
function generateSinglePdf($List) { $pdfValue = explode(',',$List); $path = $file = FCPATH."createpdf/"; foreach($pdfValue as $pdfVal) { foreach(glob("$path/{$pdfVal}*") as $imgfile) { $ext = substr(strrchr($imgfile, '.'), 1); if($ext=='pdf') { $imgName[] = basename($imgfile); } } } $count = count($imgName); $filelocation = FCPATH."/newmultigenerate"; $time = date("d-m-Y")."-".time(); $mainfilename="ID".$id."-multipdf-".$time; $filename=$mainfilename.".pdf"; $fileNL = $filelocation."/".$filename; $pdf = new MPdf(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false); $pdf->SetCreator(PDF_CREATOR); $pdf->SetAuthor('OrderCal'); $pdf->SetSubject('Invoice Pdf'); $pdf->SetKeywords('Invoice Pdf'); $pdf->setHeaderFont(Array(PDF_FONT_NAME_MAIN, '', PDF_FONT_SIZE_MAIN)); $pdf->setFooterFont(Array(PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA)); $pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED); $pdf->SetMargins(2, 10, 2,true); $pdf->SetHeaderMargin(PDF_MARGIN_HEADER); $pdf->SetFooterMargin(PDF_MARGIN_FOOTER); $pdf->SetAutoPageBreak(TRUE, 10); $pdf->setImageScale(PDF_IMAGE_SCALE_RATIO); $pdf->SetFont('times', 'BI', 10); $pdf->my_header_title = ''; for($i=0; $i<=$count;$i++) { if($imgName[$i]=="") continue; $imgUrl = FCPATH."createpdf/".$imgName[$i]; $pdf->setSourceFile($imgUrl); $tplIdx = $pdf->importPage($i); $pdf->useTemplate($tplIdx); } $pdf->Output($fileNL, 'F'); }
错误原因分析
- 循环变量误用:把数组索引
$i直接传给importPage(),但FPDI的importPage()需要的是当前PDF文件内的页码(从1开始),不是数组的循环索引。当处理第二个PDF文件时,$i已经是1,若该PDF只有2页,当$i增加到2时,就会超出该PDF的页码范围。 - 循环边界错误:
$i<=$count会导致数组越界,因为$imgName的索引范围是0到$count-1,$i=$count时访问$imgName[$i]会获取到空值。 - 未添加新页面:直接调用
useTemplate()会把内容覆盖在当前页面上,不会自动新增页面。
修复后的代码
function generateSinglePdf($List) { $pdfValue = explode(',',$List); $path = FCPATH."createpdf/"; $imgName = []; foreach($pdfValue as $pdfVal) { foreach(glob("$path/{$pdfVal}*") as $imgfile) { $ext = strtolower(substr(strrchr($imgfile, '.'), 1)); if($ext == 'pdf') { $imgName[] = basename($imgfile); } } } $count = count($imgName); $filelocation = FCPATH."/newmultigenerate"; // 确保输出目录存在 if (!is_dir($filelocation)) { mkdir($filelocation, 0755, true); } $time = date("d-m-Y")."-".time(); $mainfilename="ID".$id."-multipdf-".$time; $filename=$mainfilename.".pdf"; $fileNL = $filelocation."/".$filename; $pdf = new MPdf(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false); $pdf->SetCreator(PDF_CREATOR); $pdf->SetAuthor('OrderCal'); $pdf->SetSubject('Invoice Pdf'); $pdf->SetKeywords('Invoice Pdf'); $pdf->setHeaderFont(Array(PDF_FONT_NAME_MAIN, '', PDF_FONT_SIZE_MAIN)); $pdf->setFooterFont(Array(PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA)); $pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED); $pdf->SetMargins(2, 10, 2,true); $pdf->SetHeaderMargin(PDF_MARGIN_HEADER); $pdf->SetFooterMargin(PDF_MARGIN_FOOTER); $pdf->SetAutoPageBreak(TRUE, 10); $pdf->setImageScale(PDF_IMAGE_SCALE_RATIO); $pdf->SetFont('times', 'BI', 10); $pdf->my_header_title = ''; foreach($imgName as $pdfFile) { if(empty($pdfFile)) continue; $imgUrl = FCPATH."createpdf/".$pdfFile; // 获取当前PDF的总页数 $pageCount = $pdf->setSourceFile($imgUrl); // 循环导入当前PDF的每一页 for($pageNum = 1; $pageNum <= $pageCount; $pageNum++) { $tplIdx = $pdf->importPage($pageNum); // 获取模板尺寸 $size = $pdf->getTemplateSize($tplIdx); // 添加匹配模板尺寸的新页面 $pdf->AddPage($size['w'] > $size['h'] ? 'L' : 'P', [$size['w'], $size['h']]); // 使用模板 $pdf->useTemplate($tplIdx); } } $pdf->Output($fileNL, 'F'); }
关键改动说明
- 把数组循环改为
foreach遍历,避免索引混淆; - 对每个PDF文件,先通过
setSourceFile()返回值获取总页数,再循环导入每一页(页码从1开始); - 每次导入页面时,先调用
AddPage()创建匹配原页面尺寸的新页面,避免内容覆盖; - 添加了输出目录的创建逻辑,防止目录不存在导致保存失败;
- 统一文件后缀判断为小写,避免大小写问题。
内容的提问来源于stack exchange,提问作者user2222
相关产品推荐
相关产品推荐

