Laravel中无需Imagick为上传PDF每页添加条形码方案问询
替代Imagick的Laravel PDF每页添加条形码方案
原方案问题分析
- 依赖系统级软件Imagick/Ghostscript,部署成本高
- 转图片再转回PDF的流程效率低,大PDF(60+页)易触发超时
- 中间生成大量临时图片,占用额外磁盘资源
替代方案:纯PHP PDF操作(FPDI+TCPDF)
核心思路:直接导入原PDF的每一页,在PDF层面叠加条形码,无需图片转换,配合Laravel队列异步处理避免超时。
步骤1:安装依赖
composer require setasign/fpdi-tcpdf # 用于导入并编辑已有PDF composer require picqer/php-barcode-generator # 生成条形码
步骤2:创建队列任务(异步处理大PDF)
创建app/Jobs/AddBarcodeToPdf.php,负责核心的条码添加逻辑:
<?php namespace App\Jobs; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use setasign\Fpdi\Tcpdf\Fpdi; use Picqer\Barcode\BarcodeGeneratorPNG; use Illuminate\Support\Facades\Storage; class AddBarcodeToPdf implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; protected $attachmentId; public function __construct($attachmentId) { $this->attachmentId = $attachmentId; } public function handle() { $model = \App\Models\Attachment::findOrFail($this->attachmentId); $originalPdfPath = storage_path('app/3pagerpdf/pdf/' . $model->pdf_file_name_in_datebase); $outputFileName = time() . '_barcode_' . $model->pdf_file_name_in_datebase; $outputPdfPath = storage_path('app/3pagerpdf/modified/' . $outputFileName); // 初始化PDF编辑器 $pdf = new Fpdi(); $totalPages = $pdf->setSourceFile($originalPdfPath); // 条形码生成器 $barcodeGenerator = new BarcodeGeneratorPNG(); // 遍历每一页添加条码 for ($pageNum = 1; $pageNum <= $totalPages; $pageNum++) { // 导入原PDF页面 $templateId = $pdf->importPage($pageNum); $pageSize = $pdf->getTemplateSize($templateId); // 创建新页面(与原页面尺寸一致) $pdf->AddPage($pageSize['orientation'], [$pageSize['width'], $pageSize['height']]); $pdf->useTemplate($templateId); // 生成每页唯一的条码数据(可自定义规则) $barcodeData = "DOC-{$model->id}-PAGE-{$pageNum}"; $barcodeImageContent = $barcodeGenerator->getBarcode($barcodeData, $barcodeGenerator::TYPE_CODE_128); // 临时保存条码图片 $tempBarcodePath = storage_path('app/temp/barcode_' . $pageNum . '.png'); Storage::put('temp/barcode_' . $pageNum . '.png', $barcodeImageContent); // 设置条码位置:右下角,边距10px(可调整) $xPos = $pageSize['width'] - 100; // 条码宽度约100px $yPos = $pageSize['height'] - 50; // 条码高度约50px // 将条码添加到PDF页面 $pdf->Image($tempBarcodePath, $xPos, $yPos, 90); // 宽度90px,高度自适应 // 清理临时文件 Storage::delete('temp/barcode_' . $pageNum . '.png'); } // 保存处理后的PDF $pdf->Output($outputPdfPath, 'F'); // 更新数据库记录 $model->modified_pdf_path = "3pagerpdf/modified/{$outputFileName}"; $model->save(); } }
步骤3:修改上传接口,触发异步任务
public function uploadPdf(Request $request) { $model = new \App\Models\Attachment(); if ($request->hasFile('pdf_file_from_request')) { // 建议清理旧文件而非删除整个目录 $pdfFile = $request->file('pdf_file_from_request'); $fileName = time() . '.' . $pdfFile->getClientOriginalName(); Storage::putFileAs('3pagerpdf/pdf', $pdfFile, $fileName); $model->pdf_file_name_in_datebase = $fileName; $model->save(); // 触发队列任务,异步处理条码添加 \App\Jobs\AddBarcodeToPdf::dispatch($model->id); flash()->addSuccess('PDF上传成功,条码处理已启动,请稍后查看结果。'); return back(); } flash()->addError('未选择PDF文件'); return back(); }
方案优势
- 无系统依赖:仅需PHP Composer包,无需安装Imagick/Ghostscript
- 高效处理:直接操作PDF页面,避免图片转换的性能损耗,60+页PDF处理速度提升明显
- 避免超时:用Laravel队列异步处理,脱离HTTP请求超时限制
- 资源友好:无大量临时图片文件,磁盘占用低
注意事项
- 确保
storage/app/3pagerpdf/modified和storage/app/temp目录存在且有写入权限 - 根据需求调整条码的位置、大小、类型(支持CODE_128、EAN-13等多种格式)
- 配置Laravel队列驱动(如Database、Redis),并启动队列监听:
php artisan queue:work - 可在队列任务中添加错误捕获和重试逻辑,提升稳定性
内容的提问来源于stack exchange,提问作者Ali Muhammad
相关产品推荐
相关产品推荐

