ContentStream: bộ phát luồng nội dung PDF
Tổng quan nhanh
Phần tiêu đề “Tổng quan nhanh”Module ContentStream phát các toán tử nội dung được đánh dấu của Portable Document Format (PDF). Module này mở và đóng thẻ cấu trúc cùng artifact, theo dõi độ sâu lồng nhau và trả về vùng đệm toán tử.
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”ContentStreamBuilder là lớp duy nhất của module này. Lớp này xây dựng lớp nội dung được đánh dấu của một luồng nội dung trang. Một luồng nội dung mã hóa nội dung trang thành chuỗi toán tử — ISO 32000-2 §8. Sau đó, builder phát các toán tử nội dung được đánh dấu bao quanh nội dung đó.
append() thêm nguyên văn các byte toán tử thô. Builder không escape dữ liệu đầu vào này. Bạn chịu trách nhiệm về tính hợp lệ của dữ liệu đó. Hãy dùng ranh giới này khi HTML pipeline và module Graphics cần chèn xen kẽ các toán tử riêng của chúng.
beginTag() mở một chuỗi được gắn thẻ cấu trúc. Phương thức này phát một toán tử BDC kèm danh sách thuộc tính MCID, theo ISO 32000-2 §14.6. endTag() phát toán tử EMC tương ứng. Builder đếm độ sâu lồng nhau. Nếu bạn gọi endTag() khi không có chuỗi nào đang mở, nó sẽ ném PageLayoutException thay vì ghi một EMC không cân bằng.
beginArtifact() mở một chuỗi artifact. Hãy dùng artifact cho phần trang trí phân trang — đầu trang, chân trang, số trang và đường kẻ — vốn phải nằm ngoài cây cấu trúc, theo ISO 32000-2 §14.8.2.2. Subtype là một trong bốn giá trị ISO: Pagination, Layout, Page, hoặc Background. Hãy ưu tiên dùng enum ArtifactSubtype có kiểu. Phiên bản nạp chồng nhận chuỗi được kiểm tra hợp lệ theo enum, nên giá trị không chuẩn sẽ thất bại ngay lập tức.
relabelTag() ghi đè tại chỗ một thẻ đã được phát trước đó. finish() trả về toàn bộ vùng đệm và ném ngoại lệ nếu nội dung được đánh dấu không cân bằng. drain() trả về vùng đệm hiện có mà không kiểm tra cân bằng, dùng khi truyền theo từng phần. peek() trả về vùng đệm mà không tiêu thụ. reset() xóa trạng thái.
Bề mặt API
Phần tiêu đề “Bề mặt API”| Phương thức | Chữ ký | Vai trò |
|---|---|---|
append() | append(string $raw): void | Thêm các byte toán tử thô nguyên văn (không escape) |
beginTag() | beginTag(string $structType, int $mcid): void | Mở một chuỗi BDC cấu trúc |
endTag() | endTag(): void | Đóng chuỗi trong cùng bằng EMC |
beginArtifact() | beginArtifact(ArtifactSubtype|string $type): void | Mở một chuỗi artifact |
endArtifact() | endArtifact(): void | Đóng artifact trong cùng |
getMarkedContentDepth() | getMarkedContentDepth(): int | Trả về độ sâu lồng nhau hiện tại |
relabelTag() | relabelTag(string $old, string $new, int $mcid): void | Ghi đè tại chỗ một thẻ đã phát |
finish() | finish(): string | Trả về toàn bộ vùng đệm; ném ngoại lệ nếu không cân bằng |
drain() | drain(): string | Trả về vùng đệm mà không kiểm tra cân bằng |
peek() | peek(): string | Trả về vùng đệm mà không tiêu thụ nó |
reset() | reset(): void | Xóa toàn bộ trạng thái |
Chạy composer docs:generate-api-php -- --module=ContentStream để tạo bảng PHPDoc đầy đủ.
Mẫu mã — bắt đầu nhanh
Phần tiêu đề “Mẫu mã — bắt đầu nhanh”<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\ContentStream\ContentStreamBuilder;
$builder = new ContentStreamBuilder();
$builder->beginTag('P', mcid: 0);$builder->append("BT /F1 12 Tf 72 720 Td (Hello) Tj ET\n");$builder->endTag();
$pageContent = $builder->finish();Mẫu mã — môi trường sản xuất
Phần tiêu đề “Mẫu mã — môi trường sản xuất”Hãy dùng mẫu này để bọc một đoạn văn trong một thẻ cấu trúc và bọc chân trang trong một artifact. Mẫu này truyền vùng đệm theo từng phần bằng drain().
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Accessibility\ArtifactSubtype;use NextPDF\ContentStream\ContentStreamBuilder;
$builder = new ContentStreamBuilder();
$builder->beginTag('H1', mcid: 0);$builder->append($titleOperators);$builder->endTag();
$builder->beginArtifact(ArtifactSubtype::Pagination);$builder->append($footerOperators);$builder->endArtifact();
if ($builder->getMarkedContentDepth() !== 0) { throw new RuntimeException('Unbalanced marked content before flush.');}
$chunk = $builder->drain();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 ý”append()không escape dữ liệu đầu vào. Chỉ truyền các byte toán tử hợp lệ. Builder tin tưởng mã gọi.endTag()vàendArtifact()ném ngoại lệ khi bị tràn dưới. Đừng bao giờ đóng một chuỗi chưa được mở.finish()kiểm tra cân bằng và ném ngoại lệ khi độ sâu khác không.drain()thì không kiểm tra. Chỉ dùngdrain()khi truyền theo từng phần.- Bộ đếm độ sâu không phân biệt thẻ với artifact.
EMCđóng chuỗi trong cùng thuộc một trong hai loại. Hãy lồng các chuỗi theo đúng thứ tự. - Phiên bản nạp chồng nhận chuỗi của
beginArtifact()được kiểm tra hợp lệ theo enum. Một subtype không chuẩn sẽ thất bại ngay tại lời gọi, chứ không phải trong kết quả đầu ra. relabelTag()ghi đè một thẻ đã phát. Hãy dùng đúngmcidmà bạn đã dùng khi phát nó.
Hiệu năng
Phần tiêu đề “Hiệu năng”Mỗi thao tác là một phép nối chuỗi O(1), ngoại trừ relabelTag(), vốn thực hiện một phép ghi đè O(buffer). Module giữ một vùng đệm chuỗi và một bộ đếm độ sâu kiểu số nguyên. Module không phân tích cú pháp và chỉ cấp phát vùng đệm. Ngân sách tải tham chiếu là 1500 ms thời gian thực và 64 MB đỉnh. Module này vẫn thấp hơn mức đó rất xa.
Ghi chú bảo mật
Phần tiêu đề “Ghi chú bảo mật”append() là ranh giới tin cậy. Builder ghi byte nguyên văn, nên mã ở phía trên phải escape mọi chuỗi đi vào một toán tử literal-string. Bộ escape chuẩn là PdfStringEscaper::escapeLiteral() (ADR-015). Đừng bao giờ truyền văn bản người dùng chưa được escape qua append(). Các kiểm tra cân bằng trong endTag(), endArtifact(), và finish() ngăn một cây nội dung được đánh dấu sai định dạng đi đến Writer. Xem /modules/core/security/ để biết mô hình mối đe dọa của tài liệu.
Tuân thủ
Phần tiêu đề “Tuân thủ”Module phát các cấu trúc toán tử nội dung được đánh dấu nhất quán với ISO 32000-2: các cặp BDC/EMC kèm danh sách thuộc tính MCID theo §14.6, và các chuỗi artifact theo §14.8.2.2. Đây là các sự kiện về cách triển khai. Bằng chứng là src/ContentStream/ContentStreamBuilder.php, enum src/Accessibility/ArtifactSubtype.php, và tests/Unit/ContentStream/ContentStreamBuilderMarkedContentBalanceCoverageTest cùng với ContentStreamBuilderRelabelTagInvariantTest. Chúng không phải là tuyên bố về sự tuân thủ PDF/UA-2 hoặc PDF 2.0 đầu cuối. Một oracle bên ngoài kiểm tra hợp lệ cấu trúc tagged-PDF mà các toán tử này tham gia vào: tests/Integration/Accessibility/VeraPdfUa2GoldenTest đối chiếu một fixture được tạo ra với veraPDF cho hồ sơ PDF/UA-2. Test oracle đó bỏ qua khi không có tệp nhị phân veraPDF, nên đây là một cổng tùy chọn. Hãy phát biểu rằng module này “tạo ra các cấu trúc nội dung được đánh dấu; sự tuân thủ PDF/UA-2 được kiểm tra hợp lệ bởi veraPDF” thay vì khẳng định sự tuân thủ một cách không kèm điều kiện.