You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Setasign/FPDI合并PDF时签名等绘图内容丢失的解决方法求助

FPDI合并PDF时签名等内容丢失的解决方案

问题背景

使用Setasign/FPDI及其PDF-Parser合并多个PDF文件时,部分包含签名等绘图内容的文件,合并后签名内容消失,需确保所有PDF内容完整转移到输出文件。

原始合并代码

private function mergeFiles()
{
    $fpdi = new Fpdi();

    foreach ($files as $file) {
        $this->mergePDFFile($fpdi, $file->getFilePath());
    }

    $fpdi->Output($outputFilePath, 'F');
}


private function mergePDFFile(Fpdi $pdf, $filePath)
{
    $pageCount = $pdf->setSourceFile($filePath);

    for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) {
        $templateId = $pdf->importPage($pageNo);
        $size       = $pdf->getTemplateSize($templateId);
        $pdf->AddPage($size['orientation']);
        $pdf->useTemplate($templateId, null, null, null, null, true);
    }
}

效果对比

合并前的原始文件

合并前的原始文件

合并后的异常结果文件

合并后的异常结果文件

问题原因

FPDI默认的importPage方法仅导入页面的内容流,而PDF签名通常以注释(Annotation)或AcroForm表单字段的形式存储,这类内容不会被自动导入,因此合并后签名等内容丢失。

解决方案

方案1:基于FPDI手动导入注释与表单字段

通过FPDI的PDF解析器提取原PDF的注释和表单字段,手动添加到新生成的页面中。修改后的代码如下:

private function mergeFiles()
{
    $fpdi = new Fpdi();

    foreach ($files as $file) {
        $this->mergePDFFile($fpdi, $file->getFilePath());
    }

    $fpdi->Output($outputFilePath, 'F');
}

private function mergePDFFile(Fpdi $pdf, $filePath)
{
    $pageCount = $pdf->setSourceFile($filePath);
    // 获取原PDF的解析器实例
    $parser = $pdf->getPdfParser();
    $catalog = $parser->getCatalog();
    $acroForm = $catalog->getAcroForm();

    for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) {
        $templateId = $pdf->importPage($pageNo);
        $size = $pdf->getTemplateSize($templateId);
        $pdf->AddPage($size['orientation']);
        $pdf->useTemplate($templateId, null, null, null, null, true);

        // 导入当前页面的注释内容
        $page = $parser->getPage($pageNo);
        $annotations = $page->getAnnotations();
        foreach ($annotations as $annot) {
            $pdf->addAnnotation($annot->getDictionary());
        }

        // 导入关联当前页面的AcroForm字段
        if ($acroForm) {
            $fields = $acroForm->getFields();
            foreach ($fields as $field) {
                $fieldPage = $field->getPage();
                if ($fieldPage && $fieldPage->getNumber() === $pageNo) {
                    $pdf->addField($field->getDictionary());
                }
            }
        }
    }
}

方案2:使用SetaPDF-Merger(推荐)

Setasign官方提供的SetaPDF-Merger是专门针对PDF合并的组件,能自动处理签名、注释、表单等所有内容,无需手动编码。示例代码:

use SetaPDF_Merger;

private function mergeFilesWithMerger()
{
    $merger = new SetaPDF_Merger();

    foreach ($files as $file) {
        $merger->addFile($file->getFilePath());
    }

    // 执行合并并保存到指定路径
    $merger->merge()->save($outputFilePath);
}

说明

  • 方案1需确保FPDI版本支持注释和表单字段的导入,部分复杂签名可能仍存在兼容问题。
  • 方案2的SetaPDF-Merger为商业组件,需购买授权,但能完美保留PDF的所有元素,包括签名、表单、注释等。

内容的提问来源于stack exchange,提问作者felmez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 14:01:01