跳到內容
getnextpdf.com

穩定性: 實驗性

PageBackfill:保留頁面緩衝區

可選擇啟用的預覽。 保留頁面緩衝區預設為關閉。在它關閉的情況下,寫入器就是它一直以來的串流序列化器——位元組完全相同。只在你確實需要繪製到一個較早的頁面上時才將它開啟,並請先閱讀下方的 fail-closed 清單。

預設情況下,寫入器會串流頁面並依序將它們沖出;一個頁面一旦沖出,就無法再被繪製。保留頁面緩衝區是用來持有已沖出頁面的選擇性啟用,使一個先前已沖出的頁面能在文件被序列化之前被回填——亦即繪製到一個較早的頁面上。經典的用途是一個總計或一個摘要框,你只能在較後的頁面都配置完成之後才放置它。

Terminal window
composer require nextpdf/core:^3

保留頁面緩衝區隨核心套件一起出貨。Config::withRetainedPageBuffer()Document 的回填方法為 @since 6.1.0。預設值維持為串流寫入器。先前曾延後此能力的 ADR-037,現已記錄為已實作。

Config::withRetainedPageBuffer() 讓一份文件選擇進入保留頁面。一旦開啟,Document::setActiveBackfillPage(int $pageIndex) 會將繪製重新導向到一個較早的、已沖出的頁面;Document::endPageBackfill() 則讓繪製回到正常的附加位置。你在這兩次呼叫之間寫入的內容會落在那個較早的頁面上。緩衝區會持有頁面直到 save(),因此回填會在交叉參照表與尾端被寫出之前套用(ISO 32000-2 §7.5)。

回填是一個隨機存取操作,而有數項文件功能假定的是僅附加、串流的位元組。保留頁面緩衝區會拒絕與它們任一者結合,且不受順序影響、在序列化之前進行,因此它絕不會默默破壞一個簽章或一個一致性主張

  • 數位簽章。
  • 標記式 PDF(結構樹)。
  • PDF/A。
  • 線性化。
  • 物件串流封裝。
  • 加密。
  • Safe CSS 算繪模式。

一個逐文件的未壓縮位元組預算會為緩衝區可持有的量設限;一個超出該預算的文件會硬性失敗,而不是消耗無上限的記憶體。在沒有選擇性啟用的情況下,串流預設仍會在呼叫端嘗試一個隨機存取切換的那一刻 fail closed——開啟緩衝區是取得回填的唯一方式,而依其建構方式,它與上述各功能不相容。

符號位置角色
Config::withRetainedPageBuffer(bool $enabled = true): selfsrc/Core/Config.php讓一份文件選擇進入保留頁面緩衝區。
Document::setActiveBackfillPage(int $pageIndex): staticsrc/Core/Document.php將繪製重新導向到一個較早的、已沖出的頁面。
Document::endPageBackfill(): staticsrc/Core/Document.php讓繪製回到正常的附加位置。

一個違反某項被拒絕組合的回填嘗試,會在邊界處引發一個具型別的設定例外,而不是一份毀損的文件。

在第一頁保留一個位置,填完文件的其餘部分,然後以一個在最後才計算出的值回填那個被保留的位置。

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Config;
use NextPDF\Core\Document;
$config = (new Config())->withRetainedPageBuffer();
$doc = Document::createStandalone($config);
$doc->addPage(); // page 0 — leaves room for a grand total
$doc->writeHtml('<h1>Invoice</h1>');
$doc->addPage(); // page 1 — line items
$doc->writeHtml('<p>Line items…</p>');
$total = 1234.56; // computed after laying out the items
$doc->setActiveBackfillPage(0); // draw back onto page 0
$doc->writeHtml('<p>Grand total: ' . number_format($total, 2) . '</p>');
$doc->endPageBackfill();
$doc->save(__DIR__ . '/invoice.pdf');

對任何已簽章、已標記、PDF/A、已線性化、已加密或物件串流的文件,保持緩衝區關閉——那些正是緩衝區所拒絕的組合。請明確地選擇一條路徑。

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Config;
use NextPDF\Core\Document;
function renderReport(bool $needsBackfill, bool $mustBeSigned): Document
{
if ($needsBackfill && $mustBeSigned) {
// The buffer refuses to combine with signing. Resolve the requirement
// before building: pre-compute the value, or sign a separate pass.
throw new \LogicException('Back-fill and signing are mutually exclusive.');
}
$config = new Config();
if ($needsBackfill) {
$config = $config->withRetainedPageBuffer();
}
return Document::createStandalone($config);
}
  • 關閉時位元組完全相同。 在緩衝區關閉的情況下,寫入器會如以往一樣串流。
  • 與簽章、標記、PDF/A、線性化、物件串流、加密與 Safe CSS 模式互斥。 此拒絕不受順序影響,且在序列化之前觸發。請為文件規劃其中一種模式。
  • 位元組預算會硬性失敗。 保留緩衝區是有界的;一個超出未壓縮位元組預算的文件會失敗,而不是無上限地成長。
  • 成對呼叫。 每一次 setActiveBackfillPage() 都應由一次 endPageBackfill() 配對,使後續內容正常地附加。
  • 串流預設拒絕隨機存取。 在沒有選擇性啟用的情況下,一次隨機存取切換會 fail closed。緩衝區是唯一受支援的路徑。

保留頁面緩衝區以記憶體換取回填能力:它會持有已沖出的頁面直到 save(),並受逐文件的未壓縮位元組預算限制。串流寫入器的平坦記憶體輪廓只在緩衝區關閉時適用。performance_budgetwall_ms: 1500peak_mb: 128)反映了保留路徑較高的記憶體上限。

保留頁面緩衝區不會擴大輸入面;它改變的是位元組何時被序列化,而非何物被擷入。它拒絕與加密及簽章結合,是一項安全屬性:一個回填絕不可能在事後改變已簽章或已加密的位元組,因為這兩者無法一同啟用。位元組預算為記憶體設限,以防範一份惡意文件。

陳述規範條款
寫入器在儲存時序列化主體、交叉參照結構與尾端。ISO 32000-2§7.5

這是一項預覽能力。NextPDF 對已簽章、已標記、PDF/A、已線性化、已加密與物件串流的文件拒絕回填緩衝區,因此它透過此路徑不對那些設定檔作任何一致性主張。未重現任何規範文字。

TCPDF 相容性轉接器將此能力以一個建構函式擴充的形式公開。以 retainedPageBuffer: true 建構轉接器,那麼一次以較早頁面為目標的 setPage()lastPage() 呼叫,就會委派給核心回填,而不是引發串流的 UnsupportedFeatureException。這個建構函式引數是一個 NextPDF 擴充,而非舊版 TCPDF 對等功能——舊版 TCPDF 並沒有這樣的旗標。同樣的 fail-closed 拒絕適用。轉接器端的細節請參閱 compat 轉接器的 retained-page-buffer 頁面。