ข้ามไปยังเนื้อหา

Contracts / การแยกข้อมูล

โดเมน extraction กำหนดสัญญา (contract) สำหรับอ่านและตรวจสอบไฟล์ Portable Document Format (PDF) รวมถึงแปลงเนื้อหาในไฟล์เหล่านั้นเป็นข้อมูลแบบมีโครงสร้าง โดเมนนี้ประกอบด้วย inspector ตัวตรวจสอบความสอดคล้อง ตัวจัดการ PDF/A สัญญาของอ็อบเจกต์ที่นำเข้า สัญญาของการฝังและดัชนีเวกเตอร์ และ sub-namespace ของตัวตรวจสอบ e-invoice

Terminal window
composer require nextpdf/core:^3

InspectorInterface อ่านไบต์ดิบของ PDF และคืนค่า InspectResult แบบมีโครงสร้าง ผลลัพธ์จะแสดงรายการอ็อบเจกต์ในไฟล์ ใช้สัญญานี้กับเครื่องมือใดๆที่อ่าน PDF ซึ่งเอนจินไม่ได้เป็นผู้เขียน

ExternalComplianceValidatorInterface เชื่อมต่อเอนจินกับตัวตรวจสอบภายนอก เช่น veraPDF ตัวตรวจสอบจะทดสอบ PDF/A และ PDF/Universal Accessibility (PDF/UA) เมื่อไม่ได้กำหนดค่าตัวตรวจสอบไว้ implementation แบบ null จะคืนค่าผลลัพธ์ “unavailable” ไซต์ที่ไม่มี veraPDF จึงยังทำงานได้ ProfileValidatorInterface ตรวจสอบ runtime เทียบกับโปรไฟล์การติดตั้งใช้งาน รวมถึงส่วนขยายที่จำเป็นและที่แนะนำ แล้วคืนค่าผลตัดสินแบบมีชนิด

PdfAManagerInterface รักษาไฟล์ PDF/A ให้อยู่ในข้อกำหนดระหว่างที่ writer สร้างไฟล์ โดยปิดกั้น JavaScript การกระทำของฟอร์มแบบ JavaScript และการเข้ารหัสลับ เพราะ PDF/A ห้ามทั้งสามอย่าง นอกจากนี้ยังตรวจสอบว่าทุกฟอนต์ถูกฝังไว้ กำหนดเมตาดาทาที่เป็นไปตามข้อกำหนด และเขียนอ็อบเจกต์ที่จำเป็นก่อน catalog คลาสจริงมาพร้อมกับรุ่น Pro Core ค้นหาคลาสนั้นด้วย class_exists() แล้ว cast เป็นสัญญา เอนจินโอเพนซอร์สจึงไม่มีดีเพนเดนซีแบบเสียค่าใช้จ่าย

มีสัญญาสองรายการที่ครอบคลุมอ็อบเจกต์ที่นำเข้า ได้แก่ ImportedFormObjectInterface และ EmbeddedPdfObjectInterface สัญญาเหล่านี้ให้การเข้าถึงอ็อบเจกต์ที่อ่านจาก PDF ที่มีอยู่แบบมีชนิด เพื่อให้เอนจินฝังอ็อบเจกต์เหล่านั้นซ้ำได้ เส้นทางแบบไม่สูญเสียข้อมูลจะเก็บไบต์ดิบของ dictionary ไว้ ส่วนเส้นทางสำรองจะให้อาร์เรย์ dictionary ที่แยกวิเคราะห์แล้วสำหรับอ็อบเจกต์ที่มาจาก object stream อ็อบเจกต์ที่ฝังซ้ำแต่ละรายการเป็น PDF indirect object หมายเลขอ็อบเจกต์และหมายเลข generation เป็นตัวระบุอ็อบเจกต์นั้น ตามที่กำหนดโดย ISO 32000-2 §7.3.10

สัญญาของการฝังรองรับการค้นหา EmbeddingServiceInterface แปลงข้อความเป็น dense vector และรายงานขนาดพร้อมชื่อโมเดล เพื่อให้ผู้เรียกปรับตัวได้ขณะ runtime รุ่น Pro ใช้โมเดลแบบ central processing unit (CPU) ส่วนรุ่น Enterprise ใช้โมเดลแบบ graphics processing unit (GPU) VectorIndexInterface สร้างและค้นหาดัชนีแบบ nearest-neighbor โดยเป็นดัชนีขนาดเล็กแบบ in-process สำหรับการใช้งานใน core ส่วนการค้นหาขนาดใหญ่กว่านั้นอยู่ในสัญญาเฉพาะรุ่น Enterprise

กลุ่ม EInvoice เก็บตัวตรวจสอบ e-invoice แบบข้ามระดับชั้น ValidatorInterface ตรวจสอบ preflight บนเพย์โหลดแบบ Cross Industry Invoice (CII) หรือ Universal Business Language (UBL) SchematronRunnerInterface ตรวจรอบของกฎทางธุรกิจ ValidationResult รวบรวมสิ่งที่ตรวจพบและการละเมิดกฎ ตัวตรวจสอบต้องปฏิเสธอินพุตที่ไม่ดีด้วยผลลัพธ์ ไม่ใช่ด้วยข้อยกเว้น และต้องป้องกันเพย์โหลดที่มี Document Type Declaration (DOCTYPE) รวมถึงเพย์โหลดที่มีขนาดใหญ่เกินไป

ชนิดประเภทสมาชิกหลักเสถียรภาพตั้งแต่
InspectorInterfaceinterfaceinspect(string, InspectConfig): InspectResultexperimental2.2.0
ExternalComplianceValidatorInterfaceinterfacevalidate(string, ComplianceFlavour), isAvailable()experimental2.4.0
ProfileValidatorInterfaceinterfacevalidate(DeploymentProfile): DeploymentProfileResultexperimental2.4.0
PdfAManagerInterfaceinterfacevalidateNoJavaScript(), validateFont(), validateNoEncryption(), applyOutputProfile(), writeRequiredObjects()stable1.10.0
ImportedFormObjectInterfaceinterfacegetWidth(), getHeight(), getEmbeddedObjects(), getResourcesDict(), getMediaBox(), getContentStream()stable1.8.0
EmbeddedPdfObjectInterfaceinterfacegetRawDictionaryBytes(), getRawStreamData(), getDictionary()stable1.8.0
EmbeddingServiceInterfaceinterfaceembed(), batchEmbed(), getDimension(), getModelName()experimental2.1.0
VectorIndexInterfaceinterfacebuild(), search(), delete(), count()experimental2.1.0
EInvoice\ValidatorInterfaceinterfacevalidate(string, ValidatorContext): ValidationResultexperimental5.1.0
EInvoice\ValidationResultfinal readonly class$isValid, getErrors(), getWarnings(), fail()experimental5.1.0

เนมสเปซ EInvoice ยังเผยแพร่ SchematronRunnerInterface, ProfileInterface, ValidationFinding, RuleViolation รวมถึง enum ProfileType, RuleSeverity และ ValidationFindingLevel ด้วย

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());
}

ฟังก์ชันนี้ขึ้นอยู่กับสัญญา implementation ของ inspector ใดๆจึงสามารถตอบสนองสัญญานี้ได้

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 ที่ล้มเหลวสำหรับอินพุตที่มีรูปแบบไม่ถูกต้อง และจะไม่โยนข้อยกเว้นสำหรับการละเมิดความถูกต้องของรูปแบบ (well-formedness) ให้ตรวจสอบ $isValid อย่าครอบการเรียกด้วย try/catch สำหรับกรณีนั้น
  • ExternalComplianceValidatorInterface::isAvailable() ต้องได้รับการตรวจสอบก่อนอ้างอิงผลตัดสิน implementation แบบ null จะคืนค่า “unavailable” การถือว่าค่านั้นเป็น “non-conformant” จะทำให้เกิดผลลบลวง
  • EmbeddedPdfObjectInterface::getRawDictionaryBytes() คืนค่า null สำหรับอ็อบเจกต์ที่มาจาก object stream ให้ใช้ getDictionary() เป็นทางสำรอง อย่าสมมติว่ามีไบต์ดิบอยู่เสมอ
  • EmbeddingServiceInterface::getDimension() แตกต่างกันตามระดับชั้น โค้ดที่จัดสรรเวกเตอร์ความกว้างคงที่ต้องอ่านมิติขณะ runtime ไม่ใช่กำหนดค่าแบบตายตัว
  • VectorIndexInterface::build() กำหนดให้รายการเวกเตอร์และรายการ id มีความยาวเท่ากันและมีมิติที่สอดคล้องกัน ความไม่ตรงกันจะทำให้เกิด InvalidArgumentException จึงควรตรวจสอบรายการเหล่านั้นก่อนสร้างดัชนี

ต้นทุนของการตรวจสอบและการตรวจสอบความถูกต้องจะปรับตามขนาดเอกสารและจำนวนอ็อบเจกต์ performance_budget ที่ 1500 ms wall และ 64 MB peak ครอบคลุมเอกสารขนาดปานกลางหนึ่งฉบับ การเรียก veraPDF ภายนอกจะเพิ่มเวลาประมวลผลของตัวเอง เวลาดังกล่าวอยู่นอกงบประมาณของเอนจินและควรทำงานนอกเส้นทางคำขอ ต้นทุนการฝังจะปรับตามความยาวของข้อความ และต่ำกว่ามากเมื่อทำเป็น batch แทนที่จะทำในลูป โดยเฉพาะบนโมเดล GPU ควรเลือกใช้ batchEmbed() การค้นหาเวกเตอร์เป็นแบบ sublinear ตามขนาดดัชนีสำหรับดัชนีแบบ in-process โปรไฟล์ความสามารถในการทำซ้ำคือ structural รายงานการตรวจสอบจะบันทึก timestamp และ fingerprint ของสภาพแวดล้อม การรันสองครั้งจะแตกต่างกันในฟิลด์เหล่านั้น ขณะที่ผลตัดสินความสอดคล้องยังคงเหมือนเดิม

Extraction อ่านเอกสารที่เอนจินไม่ได้สร้างขึ้น ดังนั้นทุกอินพุตจึงไม่น่าเชื่อถือ ทั้ง inspector และตัวตรวจสอบ e-invoice ต่างแยกวิเคราะห์ไบต์ที่มาจากภายนอก ตัวตรวจสอบ e-invoice ต้องปิดกั้นเพย์โหลดที่มี Document Type Declaration (DOCTYPE) เพย์โหลดที่มีขนาดใหญ่เกินไป และเพย์โหลดที่มีอักขระควบคุมต้องห้ามก่อนการแยกวิเคราะห์ เพื่อป้องกันการโจมตีแบบ external-entity ของ Extensible Markup Language (XML) และการโจมตีแบบ billion-laughs การฝังอ็อบเจกต์ที่นำเข้าซ้ำจะคัดลอกไบต์จาก PDF ภายนอก อ็อบเจกต์ต้นทางที่เป็นอันตรายอาจมีเนื้อหามุ่งร้าย ดังนั้นการฝังซ้ำจึงเก็บไบต์ไว้โดยไม่เรียกใช้งานไบต์เหล่านั้น การบังคับใช้ PDF/A จะลบ JavaScript และการกระทำต่างๆออก ตัวจัดการ PDF/A ปฏิเสธ JavaScript และการเข้ารหัสลับ เพราะทั้งสองอย่างถูกห้ามในโปรไฟล์ และทั้งสองอย่างเป็นช่องทางการใช้งานในทางที่ผิดในเอกสารจัดเก็บถาวรที่มีอายุการใช้งานยาวนาน ให้ถือว่าเนื้อหาที่ตรวจสอบ อ็อบเจกต์ที่นำเข้า และ XML ของใบแจ้งหนี้เป็นอินพุตที่มุ่งร้ายตลอดทั้งกระบวนการ

การกล่าวอ้างมาตรฐานข้อกำหนดหลักฐาน
PDF/A-4 ห้าม JavaScript และการกระทำของฟอร์มแบบ JavaScript ตัวจัดการ PDF/A ปฏิเสธทั้งสองอย่างISO 19005-4§6.7.1อ้างอิงโดยข้อกำหนด (ไม่อยู่ใน corpus)
อ็อบเจกต์ที่ฝังซ้ำทุกรายการเป็น PDF indirect object ที่ระบุด้วยหมายเลขอ็อบเจกต์และ generationISO 32000-2§7.3.10

ISO 19005-4 ถูกอ้างอิงโดยข้อกำหนด มาตรฐานนี้ไม่อยู่ใน corpus ของการอ้างอิงที่ตรวจสอบได้ ดังนั้นจึงไม่มีการบันทึก reference_id การกล่าวอ้างเรื่อง indirect-object ของ ISO 32000-2 ถูกตรึงไว้กับ glossary การกล่าวอ้างทั้งสองเป็นการเรียบเรียงใหม่ เอนจินไม่ได้ทำซ้ำข้อความเชิงบรรทัดฐานใดๆ

Core กำหนดและตรึงสัญญาของ extraction โค้ดสำหรับการใช้งานจริงที่อยู่เบื้องหลัง PdfAManagerInterface, EmbeddingServiceInterface และ VectorIndexInterface มาพร้อมกับรุ่น Pro และ Enterprise รวมถึงโมเดลการฝังแบบ CPU และ GPU และเส้นทางการบังคับใช้ PDF/A แบบเต็มรูปแบบ Core resolve สิ่งเหล่านี้ขณะ runtime ด้วย class_exists() ดังนั้นเอนจินโอเพนซอร์สจึงไม่มีดีเพนเดนซีเชิงพาณิชย์ และ application programming interface (API) จะไม่เปลี่ยนแปลงเมื่ออัปเกรด

  • Contracts: 41 อินเทอร์เฟซสาธารณะ — ภาพรวมของ Service Provider Interface (SPI) และระดับชั้นของเสถียรภาพ
  • Contracts / Document — สัญญาของเอกสารที่สร้างตัวพา PDF/A
  • Contracts / Signing — การจัดเก็บถาวรแบบมีลายเซ็นที่จับคู่กับการบังคับใช้ PDF/A
  • Inspect — implementation ของ inspector ที่อยู่เบื้องหลัง InspectorInterface
  • Text — การแยกข้อความที่ใช้อ็อบเจกต์ที่ตรวจสอบแล้ว
  • Metadata — เมตาดาทา PDF/A ที่ตัวจัดการกำหนดค่า