Metadata: tạo gói XMP và đọc luồng
Tổng quan nhanh
Phần tiêu đề “Tổng quan nhanh”Module Metadata là lớp xử lý Extensible Metadata Platform (XMP) của engine. Module này tạo gói XMP mà một tệp Portable Document Format (PDF) mang theo dưới dạng luồng metadata. Nó đọc gói hiện có mà không cần nạp toàn bộ tài liệu vào bộ nhớ, đồng thời phát ra phần mở rộng XMP cho dấu vết kiểm toán của engine.
Cài đặt
Phần tiêu đề “Cài đặt”composer require nextpdf/core:^3Tổng quan khái niệm
Phần tiêu đề “Tổng quan khái niệm”Một PDF lưu metadata ở cấp tài liệu dưới dạng gói XMP trong luồng metadata gắn với catalog tài liệu, như được mô tả trong ISO 32000-2 §14.3. Module này đảm nhận việc tạo và xử lý gói đó. Bề mặt API của nó được chủ ý giữ nhỏ và tập trung: ba lớp nằm dưới NextPDF\Metadata\Xmp.
XmpMetadataBuilder tạo gói. Nó chuyển một tập thuộc tính thành tài liệu XMP đúng định dạng, được bọc trong các chỉ thị xử lý <?xpacket?> tiêu chuẩn. Nó dùng globally unique identifier (GUID) chuẩn của gói và byte-order mark cố định do đặc tả XMP quy định. Đầu ra là chuỗi byte mà Writer nhúng làm luồng metadata, tức biểu diễn XMP trong PDF được mô tả ở §14.3.
XmpStreamReader xử lý gói. Nó được thiết kế để xử lý dữ liệu đầu vào độc hại. Trước khi phân tích cú pháp, nguồn được truyền theo luồng thành các khối 64 KB vào một tệp tạm có giới hạn dung lượng. Trình đọc áp đặt giới hạn tổng số byte trong suốt quá trình ghi đó. Trình nạp entity của libxml được đặt thành null trong khi phân tích cú pháp và được khôi phục sau đó. Bất kỳ DOCTYPE nào cũng sẽ bị từ chối tuyệt đối. iterateProperties() trả về một generator phát ra các tuple (namespaceUri, localName, textContent) cho mỗi phần tử lá mà không dựng toàn bộ cây trong bộ nhớ; tại bất kỳ thời điểm nào, chỉ phần tử hiện tại và node văn bản của nó tồn tại trong trình phân tích cú pháp. Gói quá lớn sẽ ném ra PacketTooLargeException; Extensible Markup Language (XML) không đúng định dạng, DOCTYPE, hoặc dữ liệu đầu vào không phải UTF-8 sẽ ném ra InvalidConfigException.
XmpAuditFieldEmitter là phần mở rộng riêng của engine. Nó kết xuất một AuditReport thành trường XMP tùy chỉnh trong namespace nextpdfAudit, nhờ đó bản kiểm toán tuân thủ của tài liệu đi cùng tệp dưới dạng XMP tuân thủ tiêu chuẩn thay vì một tệp đính kèm riêng. AuditReport mà nó kết xuất không do emitter tạo ra. Bên gọi kích hoạt việc làm giàu dữ liệu bằng cách chạy một lần kết xuất ở chế độ CssRenderingMode::Audit với một auditCollector do bên gọi cung cấp, được cấu hình qua Config(auditCollector: ...). Trình thu thập do bên gọi kiểm soát: bên gọi nạp dữ liệu cho nó, còn emitter kết xuất mọi dữ liệu đã được thu thập. Nó mới hơn bề mặt XMP cốt lõi (@since 5.4.0). Builder và reader là @since 2.0.0.
Bề mặt API
Phần tiêu đề “Bề mặt API”| Lớp | Thành viên chính | Vai trò |
|---|---|---|
XmpMetadataBuilder | build(): string, XPACKET_GUID, XPACKET_BOM | Chuyển một tập thuộc tính thành gói XMP (@since 2.0.0) |
XmpStreamReader | iterateProperties(mixed $source, int $byteCap = DEFAULT_BYTE_CAP): \Generator, DEFAULT_BYTE_CAP | Trình đọc XMP có giới hạn, theo luồng, từ chối DOCTYPE (@since 2.0.0) |
PacketTooLargeException | kế thừa NextPdfException | Được ném ra khi một gói XMP vượt quá giới hạn số byte (@since 2.0.0) |
XmpAuditFieldEmitter | render(?AuditReport $report): string, NAMESPACE_URI | Kết xuất dấu vết kiểm toán thành một trường XMP tùy chỉnh (@since 5.4.0) |
Chạy composer docs:generate-api-php -- --module=Metadata để tạo bảng PHPDoc đầy đủ.
Mã ví dụ — Bắt đầu nhanh
Phần tiêu đề “Mã ví dụ — Bắt đầu nhanh”Truyền các thuộc tính theo luồng từ gói XMP hiện có với giới hạn byte tường minh.
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Metadata\Xmp\XmpStreamReader;
$reader = new XmpStreamReader();
foreach ($reader->iterateProperties(file_get_contents('/srv/in/xmp.xml'), byteCap: 1_048_576) as [$ns, $name, $value]) { printf("%s:%s = %s\n", $ns, $name, $value);}Mã ví dụ — Môi trường production
Phần tiêu đề “Mã ví dụ — Môi trường production”Đọc gói theo cách phòng thủ, rồi ánh xạ các lỗi có kiểu của module thành kết quả ở cấp ứng dụng thay vì để lỗi thô của trình phân tích cú pháp thoát ra ngoài.
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Exception\InvalidConfigException;use NextPDF\Metadata\Xmp\PacketTooLargeException;use NextPDF\Metadata\Xmp\XmpStreamReader;use Psr\Log\LoggerInterface;
final readonly class XmpIngestService{ public function __construct( private XmpStreamReader $reader, private LoggerInterface $logger, ) {}
/** * @param resource|string $source A stream resource or XMP byte string. * * @return array<string, string> Flattened "ns:name" => value map. */ public function ingest(mixed $source): array { $properties = [];
try { // Cap untrusted XMP at 4 MB regardless of the 1 GiB default. foreach ($this->reader->iterateProperties($source, byteCap: 4_194_304) as [$ns, $name, $value]) { $properties["{$ns}:{$name}"] = $value; } } catch (PacketTooLargeException $e) { $this->logger->warning('XMP packet exceeded ingest cap; rejected.', ['error' => $e->getMessage()]);
return []; } catch (InvalidConfigException $e) { $this->logger->warning('XMP packet malformed or unsafe; rejected.', ['error' => $e->getMessage()]);
return []; }
return $properties; }}Trường hợp đặc biệt và điểm cần lưu ý
Phần tiêu đề “Trường hợp đặc biệt và điểm cần lưu ý”XmpStreamReadertừ chối hoàn toàn mọi DOCTYPE. Đây là biện pháp phòng vệ trước XML External Entity (XXE), không phải tinh chỉnh kiểm tra hợp lệ; gói cần đến DOCTYPE sẽ không được chấp nhận. Hãy làm sạch nó ở lớp phía trên.- Giới hạn byte mặc định là 1 GiB (
DEFAULT_BYTE_CAP). Giá trị mặc định đó là mức trần, không phải khuyến nghị. Hãy truyền mộtbyteCapchặt chẽ cho dữ liệu đầu vào không đáng tin cậy. iterateProperties()là một generator. Hãy dùng nó một lần; lặp qua nó lần thứ hai sẽ không phát lại.- Trình đọc đặt trình nạp entity của libxml thành null trong khi phân tích cú pháp rồi khôi phục nó. Đừng chạy nó đồng thời với hoạt động phân tích cú pháp khác dựa trên libxml trong cùng một yêu cầu nếu hoạt động đó phụ thuộc vào trình nạp entity.
XmpAuditFieldEmitter::render(null)là hợp lệ và cho ra kết quả kết xuất rỗng; mộtAuditReportnull nghĩa là “không có kiểm toán”, không phải lỗi.
Hiệu năng
Phần tiêu đề “Hiệu năng”Builder có độ phức tạp tuyến tính theo số lượng thuộc tính. Mức dùng bộ nhớ của trình đọc bị chi phối bởi đoạn văn bản đơn dài nhất, chứ không phải kích thước tài liệu, vì chỉ có phần tử hiện tại tồn tại trong trình phân tích cú pháp; các gói lớn được truyền theo luồng thay vì nạp vào bộ nhớ. Khối lượng công việc tham chiếu mặc định nằm trong ngân sách 1500 ms thời gian thực / 64 MB đỉnh. Hồ sơ khả năng tái lập là structural: gói XMP ghi lại các dấu thời gian sửa đổi. Hai lần tạo cùng một metadata logic sẽ khác nhau ở những trường đó, trong khi cấu trúc của chúng giống hệt nhau.
Ghi chú bảo mật
Phần tiêu đề “Ghi chú bảo mật”XmpStreamReader phân tích cú pháp XML không đáng tin cậy và được gia cố tương ứng. Việc chia khối theo luồng cùng giới hạn byte được áp đặt sẽ hạn chế cuộc tấn công từ chối dịch vụ kiểu khuếch đại bộ nhớ. Việc từ chối DOCTYPE khép lại lỗ hổng XXE. LIBXML_NONET chặn phân giải entity qua mạng. Dữ liệu đầu vào không phải UTF-8 bị từ chối. Dù vậy, hãy đặt một byteCap phù hợp với môi trường triển khai cho bất kỳ gói nào có nguồn từ bên ngoài thay vì dựa vào giá trị mặc định cỡ gigabyte. Hãy coi các giá trị thuộc tính XMP là chuỗi không đáng tin cậy khi chúng quay trở lại ứng dụng. Xem mô hình mối đe dọa của engine trong /modules/core/security/.
Sự tuân thủ
Phần tiêu đề “Sự tuân thủ”Gói mà XmpMetadataBuilder tạo ra chính là biểu diễn luồng metadata XMP trong PDF được định nghĩa trong ISO 32000-2 §14.3 (). Bản thân dạng tuần tự hóa XMP được điều chỉnh bởi đặc tả XMP (ISO 16684-1), vốn không nằm trong kho trích dẫn có thể kiểm chứng. Yêu cầu đó được tham chiếu theo số hiệu, chứ không ghim theo từng đoạn. Đây là các sự kiện triển khai do src/Metadata/Xmp/ tạo ra và được tests/Unit/Metadata/Xmp/ kiểm thử. Sự tuân thủ metadata đầu-cuối cho một hồ sơ (PDF/A, PDF/UA) được kiểm chứng bằng các bộ oracle và golden được mô tả trong /modules/core/conformance/.
Xem thêm
Phần tiêu đề “Xem thêm”- Module Document — cây DPart đi kèm Document Part Metadata (DPM).
- Module Audit — tạo
AuditReportmà emitter kết xuất. - Module Writer — nhúng gói dưới dạng luồng metadata.
- Tổng quan về sự tuân thủ
- Mô hình bảo mật của engine