跳轉到

表單扁平化

表單扁平化(Form Flattening)將互動式 AcroForm 欄位的當前填寫內容「燒錄」到頁面內容串流中,生成不可再編輯的靜態 PDF。常用於歸檔已完成的表單、防止表單內容被篡改,以及確保在不支援 AcroForm 的閱讀器中正確顯示。

基本扁平化

use NextPDF\Form\FormFlattener;
use NextPDF\Form\FlattenOptions;
use NextPDF\Form\FlattenResult;

$flattener = FormFlattener::create();

$result = $flattener->flatten(
    sourcePdf: file_get_contents('/path/to/filled-form.pdf'),
    options: FlattenOptions::default(),
);

if ($result->isSuccess()) {
    file_put_contents('/path/to/static.pdf', $result->getPdfBytes());
}

FlattenResult

use NextPDF\Form\FlattenResult;
use NextPDF\Form\FlattenStatus;

$result = $flattener->flatten(sourcePdf: $pdfBytes);

// 檢查結果
echo $result->getStatus()->value;   // success | partial | failed
echo $result->getFlattenedCount();  // 成功扁平化的欄位數
echo $result->getSkippedCount();    // 跳過的欄位數

// 查看跳過的欄位與原因
foreach ($result->getSkippedFields() as $field) {
    echo $field->getName() . ': ' . $field->getSkipReason();
}

// 取得輸出 PDF
$flatPdfBytes = $result->getPdfBytes();

選擇性扁平化

use NextPDF\Form\FlattenOptions;

// 只扁平化特定欄位
$result = $flattener->flatten(
    sourcePdf: $pdfBytes,
    options: FlattenOptions::create(
        fields: ['firstName', 'lastName', 'email'],  // 僅扁平化指定欄位
        skipSignatureFields: true,   // 保留簽章欄位(不扁平化)
        skipEmptyFields: false,      // 即使空白也扁平化
    ),
);

// 扁平化所有欄位除了指定欄位
$result = $flattener->flatten(
    sourcePdf: $pdfBytes,
    options: FlattenOptions::create(
        excludeFields: ['digitalSignature'],
    ),
);

扁平化品質設定

$options = FlattenOptions::create(
    renderQuality: RenderQuality::High,  // Low | Medium | High | Print
    fontEmbedding: true,   // 確保扁平化後的文字使用嵌入字型
    preserveAnnotations: true, // 保留非表單的標注(如:連結、備註)
);

扁平化後的簽章保護

// 若 PDF 含有有效的數位簽章,扁平化時必須特別處理
$options = FlattenOptions::create(
    signatureHandling: SignatureHandling::PreserveValidity,
    // PreserveValidity: 增量更新(不破壞現有簽章的 ByteRange)
    // Strip: 移除所有簽章(扁平化整份文件)
);

批量扁平化

// 批量處理多份表單 PDF
$results = $flattener->flattenBatch(
    sources: [
        '/path/to/form1.pdf',
        '/path/to/form2.pdf',
        '/path/to/form3.pdf',
    ],
    options: FlattenOptions::default(),
    outputDir: '/path/to/output/',
);

foreach ($results as $filename => $result) {
    if (!$result->isSuccess()) {
        logger()->error("Failed to flatten {$filename}", ['result' => $result]);
    }
}

參見