跳到內容

契約 / 擷取

擷取領域包含讀取與驗證 PDF,以及將其內容轉為結構化資料的各項契約。這些契約涵蓋檢查器、相容性驗證器、PDF/A 管理器、匯入物件契約、嵌入與向量索引契約,以及電子發票驗證器子命名空間。

Terminal window
composer require nextpdf/core:^3

InspectorInterface 會讀取原始 PDF,並回傳結構化的 InspectResult。該結果會列出檔案中的物件。任何需要讀取非本引擎所寫 PDF 的工具,都應使用它。

ExternalComplianceValidatorInterface 會橋接外部檢查工具,例如 veraPDF。該檢查工具會測試 PDF/A 與 PDF/UA。未設定任何檢查工具時,null 版本會回傳「無法使用」的結果。未安裝 veraPDF 的站台仍可正常運作。ProfileValidatorInterface 會依部署設定檔檢查執行環境,檢視必要與建議的擴充功能,並回傳具型別的判定結果。

PdfAManagerInterface 會在寫入 PDF/A 檔案時維持其規格符合性。它會阻擋 JavaScript、JavaScript 表單動作以及內建加密;PDF/A 禁止這三者。它也會檢查每個字型都已內嵌、設定符合規格的中繼資料,並在目錄(catalog)之前先寫入所需的物件。實際的類別隨附於 Pro 版。Core 會以 class_exists() 找到它,並轉型為該契約。開放原始碼引擎因此不會帶入任何付費相依。

有兩個契約涵蓋匯入物件:ImportedFormObjectInterfaceEmbeddedPdfObjectInterface。它們為從既有 PDF 讀取的物件提供具型別的存取。引擎接著可將這些物件重新內嵌。無損路徑會保留原始字典位元組。對於取自物件串流的物件,後備路徑會提供已剖析的字典陣列。每個重新內嵌的物件都是一個 PDF 間接物件,並由物件編號與世代編號共同識別——ISO 32000-2 §7.3.10。

嵌入契約支援搜尋工作。EmbeddingServiceInterface 會將文字轉為密集向量,並回報模型維度與名稱。呼叫端可在執行階段據此調整。Pro 版執行的是 CPU 模型;Enterprise 版執行的是 GPU 模型。VectorIndexInterface 會建構最近鄰索引並對其進行搜尋。它是供核心使用的行程內小型索引。規模較大的搜尋則位於僅限 Enterprise 的契約中。

這個 EInvoice 群組包含跨版本層級使用的電子發票檢查器。ValidatorInterface 會對 CII 或 UBL 內容執行預檢。SchematronRunnerInterface 會執行商業規則檢查。ValidationResult 會收集發現項目與規則違反。檢查器必須透過結果回報拒絕不良輸入,而不是拋出例外。它也必須防範 DOCTYPE 與過大的內容。

型別種類主要成員穩定度自版本
InspectorInterfaceinterfaceinspect(string, InspectConfig): InspectResult實驗性2.2.0
ExternalComplianceValidatorInterfaceinterfacevalidate(string, ComplianceFlavour), isAvailable()實驗性2.4.0
ProfileValidatorInterfaceinterfacevalidate(DeploymentProfile): DeploymentProfileResult實驗性2.4.0
PdfAManagerInterfaceinterfacevalidateNoJavaScript(), validateFont(), validateNoEncryption(), applyOutputProfile(), writeRequiredObjects()穩定1.10.0
ImportedFormObjectInterfaceinterfacegetWidth(), getHeight(), getEmbeddedObjects(), getResourcesDict(), getMediaBox(), getContentStream()穩定1.8.0
EmbeddedPdfObjectInterfaceinterfacegetRawDictionaryBytes(), getRawStreamData(), getDictionary()穩定1.8.0
EmbeddingServiceInterfaceinterfaceembed(), batchEmbed(), getDimension(), getModelName()實驗性2.1.0
VectorIndexInterfaceinterfacebuild(), search(), delete(), count()實驗性2.1.0
EInvoice\ValidatorInterfaceinterfacevalidate(string, ValidatorContext): ValidationResult實驗性5.1.0
EInvoice\ValidationResultfinal readonly class$isValid, getErrors(), getWarnings(), fail()實驗性5.1.0

這個 EInvoice 命名空間也發布了 SchematronRunnerInterfaceProfileInterfaceValidationFindingRuleViolation,以及 ProfileTypeRuleSeverityValidationFindingLevel 列舉。

examples/contracts/extraction-quickstart.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\InspectorInterface;
use NextPDF\Inspect\InspectConfig;
/**
* Inspect a PDF and report its object count.
*
* @param InspectorInterface $inspector A configured inspector.
* @param string $pdfData Raw PDF bytes.
*/
function describe(InspectorInterface $inspector, string $pdfData): \NextPDF\Inspect\InspectResult
{
return $inspector->inspect($pdfData, new InspectConfig());
}

此函式相依於該契約;任何檢查器實作都能符合它的需求。

examples/contracts/extraction-production.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\EInvoice\ValidatorInterface;
use NextPDF\Contracts\EInvoice\ValidatorContext;
use NextPDF\Contracts\ExternalComplianceValidatorInterface;
use NextPDF\ValueObjects\ComplianceFlavour;
use Psr\Log\LoggerInterface;
final readonly class InvoiceConformanceService
{
public function __construct(
private ValidatorInterface $invoiceValidator,
private ExternalComplianceValidatorInterface $pdfaValidator,
private LoggerInterface $logger,
) {}
/**
* Validate the invoice XML, then the PDF/A-3 carrier.
*
* @param string $xml The CII or UBL invoice payload.
* @param string $pdfPath Absolute path to the PDF/A-3 carrier.
*/
public function validate(string $xml, string $pdfPath, ValidatorContext $ctx): bool
{
$result = $this->invoiceValidator->validate($xml, $ctx);
if (!$result->isValid) {
$this->logger->warning('Invoice XML invalid', [
'errors' => \count($result->getErrors()),
]);
return false;
}
if (!$this->pdfaValidator->isAvailable()) {
$this->logger->info('PDF/A validator unavailable; skipping carrier check.');
return true;
}
$carrier = $this->pdfaValidator->validate($pdfPath, ComplianceFlavour::PdfA3b);
return $carrier->isConformant();
}
}

此服務會明確處理驗證器無法使用的情況,不會假設驗證器一定存在。

  • EInvoice\ValidatorInterface::validate() 對格式錯誤的輸入會回傳失敗的 ValidationResult。它不會因為格式正確性違反而拋出例外。請檢查 $isValid,不要為了這種情況以 try/catch 包住該呼叫。
  • ExternalComplianceValidatorInterface::isAvailable() 必須在仰賴判定結果之前先行檢查。null 實作會回傳「無法使用」。將它視為「不符合規範」會產生偽陰性。
  • EmbeddedPdfObjectInterface::getRawDictionaryBytes() 對取自物件串流的物件會回傳 null。請改用 getDictionary() 作為後備,不要假設原始位元組一定存在。
  • EmbeddingServiceInterface::getDimension() 會因版本層級而異。配置固定寬度向量的程式碼必須在執行階段讀取維度,而不是寫死它。
  • VectorIndexInterface::build() 要求向量清單與 id 清單長度相等且維度一致。不一致會引發 InvalidArgumentException。請在建構之前先驗證。

檢查與驗證成本會隨文件大小與物件數量增加。1500 毫秒牆鐘時間與 64 MB 尖峰記憶體的 performance_budget 涵蓋單一中等規模文件。外部 veraPDF 呼叫還會增加該驗證器本身的處理時間。這段處理時間不計入引擎預算,應在請求路徑之外執行。嵌入成本會隨文字長度增加,且批次處理遠比逐筆迴圈呼叫便宜,在 GPU 模型上尤其如此。請優先使用 batchEmbed()。就行程內索引而言,向量搜尋相對於索引大小是次線性的。再現性設定檔為 structural。驗證報告會記錄時間戳記與環境指紋。兩次執行在這些欄位上會有差異,而符合規範的判定結果則維持相同。

擷取會讀取非本引擎建立的文件,因此每筆輸入都不可信。檢查器與電子發票驗證器都會剖析外部提供的位元組。電子發票驗證器必須在剖析之前先攔下帶有 DOCTYPE、過大,或含有禁用控制字元的內容,以防範 XML 外部實體與 billion-laughs 攻擊。匯入物件的重新內嵌會從外來 PDF 複製位元組。惡意來源物件可能挾帶有害內容,因此重新內嵌會保留位元組,但不執行其中內容。PDF/A 強制機制會剝除 JavaScript 與動作。PDF/A 管理器會拒絕 JavaScript 與加密,因為兩者在該設定檔中皆遭禁止,也都可能成為長期保存封存文件中的濫用途徑。請全程將受檢查的內容、匯入物件與發票 XML 視為惡意輸入。

主張標準條款佐證
PDF/A-4 禁止 JavaScript 與 JavaScript 表單動作;PDF/A 管理器會拒絕兩者。ISO 19005-4§6.7.1由條款引用(不在語料庫中)
每個重新內嵌的物件都是以物件編號與世代識別的 PDF 間接物件。ISO 32000-2§7.3.10

ISO 19005-4 是依條款引用。它不在可驗證的引用語料庫中,因此不會記錄 reference_id。ISO 32000-2 的間接物件主張已釘選於詞彙表。兩者皆為改寫。引擎不會重現任何規範性文字。

Core 定義並凍結擷取契約。PdfAManagerInterfaceEmbeddingServiceInterfaceVectorIndexInterface 背後的正式環境程式碼隨附於 Pro 與 Enterprise 版,包含 CPU 與 GPU 嵌入模型,以及完整的 PDF/A 強制路徑。Core 會在執行階段以 class_exists() resolve(解析)這些類別。開放原始碼引擎因此不帶任何商業相依,升級時 API 也不會變動。