Contracts / การแยกข้อมูล
โดยสรุป
หัวข้อที่มีชื่อว่า “โดยสรุป”โดเมน extraction กำหนดสัญญา (contract) สำหรับอ่านและตรวจสอบไฟล์ Portable Document Format (PDF) รวมถึงแปลงเนื้อหาในไฟล์เหล่านั้นเป็นข้อมูลแบบมีโครงสร้าง โดเมนนี้ประกอบด้วย inspector ตัวตรวจสอบความสอดคล้อง ตัวจัดการ PDF/A สัญญาของอ็อบเจกต์ที่นำเข้า สัญญาของการฝังและดัชนีเวกเตอร์ และ sub-namespace ของตัวตรวจสอบ e-invoice
การติดตั้ง
หัวข้อที่มีชื่อว่า “การติดตั้ง”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) รวมถึงเพย์โหลดที่มีขนาดใหญ่เกินไป
พื้นผิว API
หัวข้อที่มีชื่อว่า “พื้นผิว API”| ชนิด | ประเภท | สมาชิกหลัก | เสถียรภาพ | ตั้งแต่ |
|---|---|---|---|---|
InspectorInterface | interface | inspect(string, InspectConfig): InspectResult | experimental | 2.2.0 |
ExternalComplianceValidatorInterface | interface | validate(string, ComplianceFlavour), isAvailable() | experimental | 2.4.0 |
ProfileValidatorInterface | interface | validate(DeploymentProfile): DeploymentProfileResult | experimental | 2.4.0 |
PdfAManagerInterface | interface | validateNoJavaScript(), validateFont(), validateNoEncryption(), applyOutputProfile(), writeRequiredObjects() | stable | 1.10.0 |
ImportedFormObjectInterface | interface | getWidth(), getHeight(), getEmbeddedObjects(), getResourcesDict(), getMediaBox(), getContentStream() | stable | 1.8.0 |
EmbeddedPdfObjectInterface | interface | getRawDictionaryBytes(), getRawStreamData(), getDictionary() | stable | 1.8.0 |
EmbeddingServiceInterface | interface | embed(), batchEmbed(), getDimension(), getModelName() | experimental | 2.1.0 |
VectorIndexInterface | interface | build(), search(), delete(), count() | experimental | 2.1.0 |
EInvoice\ValidatorInterface | interface | validate(string, ValidatorContext): ValidationResult | experimental | 5.1.0 |
EInvoice\ValidationResult | final readonly class | $isValid, getErrors(), getWarnings(), fail() | experimental | 5.1.0 |
เนมสเปซ EInvoice ยังเผยแพร่ SchematronRunnerInterface, ProfileInterface, ValidationFinding, RuleViolation รวมถึง enum ProfileType, RuleSeverity และ ValidationFindingLevel ด้วย
ตัวอย่างโค้ด — เริ่มต้นอย่างรวดเร็ว
หัวข้อที่มีชื่อว่า “ตัวอย่างโค้ด — เริ่มต้นอย่างรวดเร็ว”<?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 ใดๆจึงสามารถตอบสนองสัญญานี้ได้
ตัวอย่างโค้ด — การใช้งานจริง
หัวข้อที่มีชื่อว่า “ตัวอย่างโค้ด — การใช้งานจริง”<?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 ที่ระบุด้วยหมายเลขอ็อบเจกต์และ generation | ISO 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 ที่ตัวจัดการกำหนดค่า