Pro 版本
Merge — 深入參考
本頁是 NextPDF Pro Merge 模組 NextPDF\Pro\Merge 的合約層級參考。SmartMerger 將數份輸入文件組裝為一份,並套用 Pro 增強功能:從各輸入標籤產生的整併書籤樹、整份文件去重、各輸入的頁面範圍選取,以及內部連結偵測。SemanticSplitter 是搭配的結構感知切分進入點。本頁陳述公開 API、可觀察的行為合約、資源界限與失敗模式。任務導向的設定與範例位於 Merge 能力頁面。
供應與授權
標題為「供應與授權」的區段此能力隨附於 NextPDF Pro(nextpdf/pro),並以 Pro 階層的授權封套啟用。未持有該權益的部署不會載入此能力的類別。比較版本並取得授權。
沒有任何執行階段能力旗標控管此模組。只要安裝並授權 nextpdf/pro,Merge 類別即可使用。
公開 API 介面
標題為「公開 API 介面」的區段| 符號 | 參數 | 預設行為 | 回傳 | 拋出或失敗於 | 備註 |
|---|---|---|---|---|---|
SmartMerger::__construct() | ?PdfMerger $coreMerger = null, ?PdfSplitter $splitter = null | 接受並忽略舊版 core merger;null 的 splitter 會建構預設的 Pro splitter | — | — | $coreMerger 僅為向後相容的建構而保留 |
SmartMerger::merge() | list<MergeInput> $inputs, SmartMergeConfig $config = new SmartMergeConfig() | 縮減頁面範圍、對整份輸入去重、委派基礎組裝,接著依設定注入書籤並計數連結 | SmartMergeResult | 輸入清單為空時拋出 InvalidArgumentException;輸入數量超過 maxInputs 或某個輸入超過 maxBytesPerInput 時拋出 OverflowException | 唯一的合併進入點 |
MergeInput::__construct() | string $pdfData, list<PageRange> $pageRanges = [], string $label = '' | 值物件;$pageRanges 為空會選取所有頁面 | — | — | 唯讀 |
MergeInput::hasPageRanges() | — | 當輸入帶有至少一個頁面範圍時為 True | bool | — | — |
SmartMergeConfig::__construct() | bool $consolidateBookmarks = true, bool $deduplicatePages = false, bool $rewriteLinks = true, int $maxInputs = 100, int $maxBytesPerInput = 100_000_000 | 持有增強開關與資源界限的值物件 | — | — | 唯讀;去重需明確啟用 |
SmartMergeConfig::default() | — | 書籤與連結掃描開啟、去重關閉 | self | — | 靜態工廠 |
SmartMergeConfig::basic() | — | 所有增強關閉;僅做基礎串接 | self | — | 靜態工廠 |
SmartMergeResult::__construct() | string $pdfData, int $totalPages, int $sourceCount, int $mergedSize, int $bookmarksAdded = 0, int $duplicatesRemoved = 0, int $linksRewritten = 0, list<string> $inputLabels = [] | 承載合併後位元組與整併統計的唯讀載體 | — | — | 唯讀 |
SmartMergeResult::isValid() | — | 當輸出以 %PDF 標頭開頭時為 True | bool | — | 僅檢查標頭 |
SmartMergeResult::hasOptimizations() | — | 當有任何重複被移除或有任何連結被計數時為 True | bool | — | — |
SemanticSplitter::__construct() | ?PdfSplitter $splitter = null | null 引數會建構預設的 Pro splitter | — | — | 供測試用的建構子注入 |
SemanticSplitter::splitByStructure() | string $pdfData, float $headingFontThreshold = 14.0 | 偵測標題級的 Tf 運算子作為區段起點並於這些邊界切分;未偵測到結構時回傳單一整份文件區段 | SplitResult | 緩衝區為空或缺少 %PDF 標頭時拋出 InvalidArgumentException;輸入超過 100 MB 時拋出 OverflowException | 退回 Core 的頁面範圍切分 |
進入點簽章
標題為「進入點簽章」的區段public function __construct( ?PdfMerger $coreMerger = null, ?PdfSplitter $splitter = null,)
public function merge( array $inputs, SmartMergeConfig $config = new SmartMergeConfig(),): SmartMergeResultpublic function __construct( public string $pdfData, public array $pageRanges = [], public string $label = '',)
public function hasPageRanges(): boolpublic function __construct( public bool $consolidateBookmarks = true, public bool $deduplicatePages = false, public bool $rewriteLinks = true, public int $maxInputs = 100, public int $maxBytesPerInput = 100_000_000,)
public static function default(): self
public static function basic(): selfpublic function isValid(): bool
public function hasOptimizations(): boolpublic function __construct(?PdfSplitter $splitter = null)
public function splitByStructure( string $pdfData, float $headingFontThreshold = 14.0,): SplitResult行為合約
標題為「行為合約」的區段合併管線
標題為「合併管線」的區段SmartMerger::merge() 執行一個固定管線,從外部觀察如下。
- 空的輸入清單會引發
InvalidArgumentException。接著輸入數量受maxInputs約束;超出時引發OverflowException。 - 每個輸入在使用前會依
maxBytesPerInput檢查大小。當輸入宣告了頁面範圍時,會先透過 Pro splitter 縮減為所選頁面,然後只提供那些頁面。 - 當啟用
deduplicatePages時,每份輸入文件的完整位元組字串會以非密碼學的xxh128函式計算指紋。位元組與較早輸入完全相符的輸入會被捨棄。去重作用於整份文件且以位元組精確比對。 - 基礎組裝委派給 Pro
PdfSplitter::mergeDocuments()引擎,它會將每個輸入重新編號至一個連續的物件空間,並產出一個真實的交叉參照表。 - 當啟用
consolidateBookmarks且至少一個輸入帶有非空標籤時,會套用書籤整併。會插入一個最小的/Outlinesdictionary,由文件 catalog 連結,並依合併順序為每個輸入建立一個 outline 項目。 - 當啟用
rewriteLinks時,會掃描合併輸出中的/S /GoTo動作並回報其數量。
結果統計
標題為「結果統計」的區段SmartMergeResult 回報合併後的位元組以及統計。totalPages 來自基礎合併。sourceCount 是原始輸入數量,於去重之前取得。mergedSize 是輸出的位元組長度。bookmarksAdded 只計數提供了非空標籤的輸入。duplicatesRemoved 計數被捨棄的整份輸入。linksRewritten 是偵測到的 GoTo 數量。inputLabels 依合併順序列出解析後的標籤。isValid() 檢查 %PDF 標頭;hasOptimizations() 在有重複被移除或有連結被計數時為 true。
書籤標題
標題為「書籤標題」的區段每個 outline 項目以 /Title 承載輸入標籤,並依 ISO 32000-2:2020 §7.3.4.2 逸出為 PDF literal string。會先將反斜線加倍、逸出括號、具名控制位元組使用其既定序列,任何剩餘的不可列印位元組則轉為三位數八進位逸出。因此惡意標籤無法使 literal-string 分隔符失去同步,也無法注入物件結構。標籤為空的輸入會取得 Document N 的佔位標題,從 1 起算。
基礎組裝
標題為「基礎組裝」的區段舊版 Core PdfMerger::merge() 在此版本中是刻意的 fail-closed stub;SmartMerger 從不呼叫它。基礎合併改為透過 Pro PdfSplitter::mergeDocuments() 執行,因此合併後的檔案會依 ISO 32000-2:2020 §7.5.4 為每個間接物件各一筆項目、承載一個位元組精確的交叉參照表。決定性遵循 Pro splitter 的既載設定檔:相同的輸入與設定會產生穩定的位元組串流。
結構感知切分
標題為「結構感知切分」的區段SemanticSplitter::splitByStructure() 掃描頁面內容串流中大於或等於 headingFontThreshold(預設 14.0)的 Tf 設定字型運算子,並將每個這樣的頁面視為區段起點。邊界會轉換為頁面範圍並委派給 Pro PdfSplitter::split()。當未偵測到邊界時,整份文件會作為單一區段回傳。輸入必須以 %PDF 開頭並維持在 100 MB 界限內。
邊界案例與失敗模式
標題為「邊界案例與失敗模式」的區段- 空的輸入清單會在任何組裝之前以
InvalidArgumentException失敗。 - 輸入數量超過
maxInputs(預設 100),或任何輸入超過maxBytesPerInput(預設 100 MB),會以OverflowException失敗。兩個界限都是刻意的 fail-closed 拒絕,而非暫時性錯誤。 - 去重作用於整份文件且以位元組精確比對。兩個算繪結果相同但有任何位元組不同的輸入都會被保留,且儘管
deduplicatePages名稱偏向頁面導向,duplicatesRemoved計數的是被捨棄的整份輸入。 sourceCount反映的是原始輸入數量,而非去重之後的文件數量。- 書籤整併只在至少一個輸入具有非空標籤時才觸發。若
consolidateBookmarks為 true 但每個標籤皆為空,則不會寫出任何/Outlines物件。 - 注入的 outline 項目帶有標題以及
/Parent、/Prev、/Next樹狀連結;在此版本中它們不會內嵌明確的/Dest目的地。 - 連結改寫只計數
/S /GoTo動作;它不會跨重新編號的物件重新指向目的地。請將linksRewritten視為偵測數量。 SemanticSplitter的偵測是語彙式的。它以Tf字型大小運算子為依據,因此純影像或以不尋常方式編碼的頁面不會產生邊界,會回傳單一整份文件區段。
FIPS 模式行為
標題為「FIPS 模式行為」的區段此模組不進行任何密碼學運算,因此不存在任何 FIPS 模式專屬行為。用於去重的 xxh128 內容指紋是非密碼學的變更偵測雜湊,不具備任何完整性或證據上的分量。
一致性
標題為「一致性」的區段| 主張 | 標準 | 條款 |
|---|---|---|
整併書籤以 /Outlines dictionary 寫出並由文件 catalog 連結 | ISO 32000-2:2020 | §7.7.2 |
| 基礎合併為每個間接物件產出位元組精確的交叉參照表 | ISO 32000-2:2020 | §7.5.4 |
| outline 項目標題逸出為 PDF literal string,並處理反斜線與括號 | ISO 32000-2:2020 | §7.3.4.2 |
| 完整的跨文件連結重新解析 | — | 不支援(僅偵測 GoTo) |
| 明確的各區段 outline 目的地 | — | 此版本不產出 |
所有條款皆為改寫;NextPDF 不重製規範性文字。這些是能力陳述,而非認證;NextPDF 未持有任何認證,亦不授予任何認證。
開發備註
標題為「開發備註」的區段- 在 Pro 套件中的供應狀態:
SmartMerger、MergeInput、SmartMergeConfig、SmartMergeResult與SemanticSplitter自 2.2.0 起提供。全部在nextpdf/pro3.1.0 中為現行版本。 - 基礎合併委派給 Pro
PdfSplitter::mergeDocuments()。舊版 CorePdfMerger::merge()在此版本中是 fail-closed stub,從不被呼叫。 - 只有在輸入可能是位元組完全相同的整份文件時才啟用
deduplicatePages;它不會合併近似重複或重新編碼的副本。 - 純串接使用
SmartMergeConfig::basic(),書籤加連結掃描使用::default()。 - 合併不可信輸入時請攔截
OverflowException;數量與大小界限是刻意的拒絕。 - 簡單的頁面範圍切分請直接優先使用 Pro
PdfSplitter;只有在需要標題驅動的分段時才採用SemanticSplitter。
出版邊界
標題為「出版邊界」的區段本頁只記載外部可觀察的行為以及受支援的公開 API 介面。內部命名空間路徑、輔助類別、機制表格、runbook 檔名與工單前綴皆不在範圍內。
另請參閱
標題為「另請參閱」的區段- Merge(能力) — 安裝、快速開始與正式環境範例。
- Toc — 深入參考
- Diff — 深入參考
- Document — 深入參考 — Pro splitter 與基礎合併引擎。