Kết xuất HTML thành trang PDF
Tổng quan nhanh
Phần tiêu đề “Tổng quan nhanh”Dùng writeHtml() để kết xuất một đoạn Hypertext Markup Language (HTML) và Cascading Style Sheets (CSS) thành nội dung trang Portable Document Format (PDF). Hãy truyền vào mã đánh dấu; NextPDF sẽ kết xuất một trang đã được định dạng. Phiên bản đầy đủ có thể chạy của đoạn mã này là examples/08-html-basic.php. Hãy làm theo các bước bên dưới hoặc sao chép trực tiếp ví dụ.
NextPDF đọc HTML của bạn một lần rồi truyền kết quả thẳng vào trang. Đây là pipeline truyền dữ liệu một lượt. Bạn không cần hiểu mô hình đó để dùng công thức này. Tuy nhiên, hãy ghi nhớ điều này, vì nó giải thích một số quy tắc ở phần sau của trang.
Cài đặt
Phần tiêu đề “Cài đặt”composer require nextpdf/core:^3Lệnh này cài đặt gói nextpdf/core. Các ví dụ trên trang này chạy trên PHP 8.4, và runtime được hỗ trợ là >=8.4 <9.0.
Tổng quan khái niệm
Phần tiêu đề “Tổng quan khái niệm”writeHtml() nhận một chuỗi HTML và vẽ nó vào trang hiện tại, bắt đầu từ vị trí hiện tại của con trỏ. Bên trong engine, NextPDF quét HTML của bạn một lần và tách nó thành các token (HtmlTokenizer). Sau đó, nó duyệt danh sách đó từ trái sang phải (HtmlParser). Với mỗi phần tử, nó ghi các lệnh vẽ PDF tương ứng, gọi là content-stream operator, vào một bộ đệm. Engine không bao giờ dựng hoặc giữ một cây phần tử trong bộ nhớ giữa các lần gọi. Thiết kế có chủ ý này chính là mô hình truyền dữ liệu một lượt được ghi trong ADR-001.
Mỗi phần tử khối được hỗ trợ trở thành một hộp bố cục, và mỗi đoạn văn bản trở thành một text-show operator. Các style từ thuộc tính style nội tuyến và một khối <style> được phân giải theo CSS cascade, tức là các quy tắc quyết định style nào thắng khi có nhiều style cùng áp dụng. Việc xuống dòng, căn chỉnh và giãn cách văn bản tuân theo mô hình CSS Text, vốn định nghĩa cách văn bản nguồn trở thành văn bản đã định dạng và đã ngắt dòng (W3C CSS Text Level 3).
Nếu bạn không chọn phông chữ, văn bản nội dung sẽ dùng một mặt chữ mặc định. Mặc định này là một phông Type 1 chuẩn, một trong 14 phông chuẩn được nêu tên trong ISO 32000-2. Mặc định chỉ thay đổi khi bạn đăng ký và chọn phông chữ của riêng mình, hoặc khi một hồ sơ tuân thủ yêu cầu NextPDF nhúng một phông thay thế.
Hãy đặt kỳ vọng ngay từ đầu: NextPDF hỗ trợ một tập con của HTML và CSS, không phải toàn bộ HTML và CSS. Công thức này trình bày tập con được hỗ trợ. Nó không khẳng định hỗ trợ đầy đủ HTML hay đầy đủ CSS. Để biết trạng thái chính xác đã được kiểm chứng của từng module, hãy xem bảng hỗ trợ CSS.
Bề mặt API
Phần tiêu đề “Bề mặt API”Chữ ký của phương thức là writeHtml(string $html): static. Nó được khai báo trên interface NextPDF\Contracts\PdfDocumentInterface và được hiện thực trong NextPDF\Core\Concerns\HasTextOutput. Phương thức này kết xuất vào trang hiện tại và tạo một trang cho bạn nếu chưa có trang nào. Bảng PHPDoc đầy đủ của phương thức được tạo từ mã nguồn.
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\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('HTML Basic');$doc->addPage();
$doc->writeHtml('<h1>HTML Rendering in NextPDF</h1><p>Rendered with <strong>writeHtml()</strong>.</p>');
$doc->save(__DIR__ . '/out.pdf');Mẫu mã — Production
Phần tiêu đề “Mẫu mã — Production”Đây là ví dụ đầy đủ, độc lập mà bộ test harness chạy. Nó phản chiếu examples/08-html-basic.php. Thay vì gán cứng một đường dẫn đầu ra, nó ghi vào đường dẫn do harness cung cấp. Nhờ vậy, reproducibility harness có thể chạy script hai lần và so sánh kết quả.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('HTML Basic');$doc->addPage();
$html = <<<'HTML'<h1 style="color: #1E3A8A;">HTML Rendering in NextPDF</h1>
<p>NextPDF renders <strong>HTML content</strong> directly into PDF pages.This is the recommended approach for <em>mixed formatting</em>.</p>
<h2>Supported elements</h2>
<ul> <li>Headings (h1-h6)</li> <li>Paragraphs with <strong>bold</strong> and <em>italic</em></li> <li>Ordered and unordered lists</li> <li>Tables with borders and alignment</li> <li>Inline styles (color, font-size, margin)</li></ul>
<h2>Ordered list</h2>
<ol> <li>Create a Document instance</li> <li>Add pages and content</li> <li>Call save() or output()</li></ol>HTML;
$doc->writeHtml($html);
// The harness sets NEXTPDF_COOKBOOK_OUTPUT and runs this script twice.// Honour it: do not hard-code a path, do not echo the PDF to STDOUT.$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');$doc->save($out !== false ? $out : __DIR__ . '/render-html-to-pdf.pdf');
echo "Wrote render-html-to-pdf.pdf\n";STDOUT được mong đợi:
Wrote render-html-to-pdf.pdfTrường hợp đặc biệt & lưu ý
Phần tiêu đề “Trường hợp đặc biệt & lưu ý”- Vị trí con trỏ.
writeHtml()di chuyển con trỏ đến cuối nội dung đã kết xuất. Một lệnhcell()tiếp theo hoặc một lệnhwriteHtml()thứ hai sẽ tiếp tục từ đó, không phải từ đầu trang. - Chưa có trang nào. Nếu chưa có trang nào,
writeHtml()sẽ thêm một trang trước khi kết xuất. Hãy gọiaddPage()trước nếu bạn cần đặt một cỡ trang cụ thể. - Giới hạn số phần tử và độ lồng nhau. Engine truyền dữ liệu áp dụng giới hạn
50,000phần tử và giới hạn lồng nhau 100 cấp (ADR-001). Tài liệu vượt quá một trong hai giới hạn sẽ bị từ chối thay vì bị cắt bớt một cách âm thầm. - Mã đánh dấu không được hỗ trợ. Các phần tử và thuộc tính nằm ngoài tập con được hỗ trợ sẽ bị bỏ qua hoặc dùng giá trị dự phòng; chúng không gây ra lỗi. Hãy kiểm tra phạm vi hỗ trợ trong bảng hỗ trợ CSS trước khi dựa vào một thuộc tính.
- Tài nguyên bên ngoài. Hình ảnh và stylesheet từ xa tuân theo chính sách tài nguyên bên ngoài; chính sách mặc định không tải về các URL từ xa tùy ý.
Hiệu năng
Phần tiêu đề “Hiệu năng”Việc token hóa và kết xuất diễn ra trong một lượt trên dữ liệu đầu vào của bạn, nên chi phí xử lý tăng tuyến tính theo số lượng token, O(n). Ngân sách mặc định cho công thức này là wall_ms: 1500, peak_mb: 96. Vì engine truyền dữ liệu đầu ra và không giữ Document Object Model (DOM) nào trong bộ nhớ, bộ nhớ đỉnh phụ thuộc vào bộ đệm content-stream và ngăn xếp style đang hoạt động, chứ không phụ thuộc vào toàn bộ kích thước tài liệu.
Trích đoạn bảng hỗ trợ CSS (chỉ các hàng đã kiểm chứng)
Phần tiêu đề “Trích đoạn bảng hỗ trợ CSS (chỉ các hàng đã kiểm chứng)”Trích đoạn này chỉ bao gồm các hàng được xếp loại Đã kiểm chứng trong bảng hỗ trợ CSS đã qua kiểm toán tính xác thực. “Đã kiểm chứng” nghĩa là có một hiện thực trong src/Html/ và một bộ fixture chuyên biệt, đáng kể, chạy một cách tất định dưới hồ sơ cấu trúc.
| Module W3C | Cấp | Trạng thái | Bằng chứng |
|---|---|---|---|
CSS Flexible Box Layout (css_flexbox_1) | 1 | Đã kiểm chứng | src/Html/Flex/, tests/Unit/Html/Flex/ |
CSS Grid Layout (css_grid_1) | 1 | Đã kiểm chứng | src/Html/Grid/, kho ngữ liệu WPT |
CSS Cascading and Inheritance (css_cascade_3) | 3 | Đã kiểm chứng | src/Html/Cascade/, tests/Unit/Html/Cascade/ |
CSS Table (css_tables_3) | 3 | Đã kiểm chứng | src/Html/Table/, fixture bảng + golden PDF |
CSS Fonts (css_fonts_4) | 4 | Đã kiểm chứng | src/Html/FontFace/, tests/Unit/Html/FontFace/ |
Các thuộc tính như text-align, text-indent, và color được xếp loại “Đã tuyên bố” trong bảng (đã hiện thực nhưng không có fixture module chuyên biệt), nên chúng không được liệt kê là Đã kiểm chứng ở đây.
Ràng buộc của truyền dữ liệu một lượt (ADR-001)
Phần tiêu đề “Ràng buộc của truyền dữ liệu một lượt (ADR-001)”Engine HTML không giữ DOM nào. Trạng thái của nó là một con trỏ vô hướng cùng với một ngăn xếp style push/pop; các nút văn bản chỉ chứa khoảng trắng bị loại bỏ khi token hóa. Một hệ quả là phần tử xuất hiện sau không thể đặt lại style cho phần tử trước đó, và các selector cần ngữ cảnh toàn bộ cây (ví dụ, các trường hợp :has() phức tạp) bị ràng buộc theo ADR-006. Hãy lập kế hoạch bố cục chỉ dựa vào thứ tự tài liệu.
Hợp đồng giữa các lớp (ADR-010)
Phần tiêu đề “Hợp đồng giữa các lớp (ADR-010)”Phân tích cú pháp, bố cục và vẽ là các lớp riêng biệt. Bộ phân tích cú pháp không phát ra các paint operator thô, và việc điều phối bố cục không phân tích CSS. Việc vượt qua các ranh giới đó là khoản nợ kết nối mà ADR-010 cấm. Đối với người viết công thức, điều này nghĩa là điểm vào công khai là writeHtml(). Đừng can thiệp vào nội bộ của bộ phân tích cú pháp.
Ngân sách bộ nhớ cho tài liệu lớn
Phần tiêu đề “Ngân sách bộ nhớ cho tài liệu lớn”Theo ADR-020, các ngữ cảnh định dạng trong phạm vi vùng chứa (flex, table) có thể dựng một cây con tạm thời, bị giới hạn ở 5,000 nút mỗi ngữ cảnh, sâu 20 cấp, với trần bộ nhớ hoạt động 50 MB trên tất cả các ngữ cảnh đang hoạt động và 10 cấp lồng nhau. Ngoài các ngữ cảnh đó, mô hình truyền dữ liệu không giữ cây nào. Hãy giữ từng bảng và vùng chứa flex trong giới hạn số nút để bộ nhớ có thể dự đoán được.
Ghi chú bảo mật
Phần tiêu đề “Ghi chú bảo mật”Hãy coi dữ liệu HTML đầu vào là không đáng tin cậy. NextPDF không thực thi script, và chính sách tài nguyên bên ngoài mặc định không tải về các URL từ xa tùy ý, nên bản thân engine đã thận trọng. Dù vậy, hãy kiểm tra hoặc làm sạch bất kỳ HTML nào bạn ghép từ dữ liệu người dùng nhập trước khi kết xuất nó. Giới hạn số phần tử và độ lồng nhau cũng bảo vệ bạn: chúng giới hạn lượng công việc mà một tài liệu thù địch hoặc dị dạng có thể đòi hỏi.
Tuân thủ
Phần tiêu đề “Tuân thủ”| Phát biểu | Đặc tả | Điều khoản | reference_id |
|---|---|---|---|
| CSS Text kiểm soát việc chuyển đổi văn bản nguồn thành văn bản đã định dạng và đã ngắt dòng. | W3C CSS Text Level 3 | css_text_3#x1.x2.p4 | |
| Mặt chữ nội dung mặc định phân giải thành một phông Type 1 chuẩn. | ISO 32000-2 | iso32000_2_sec9#x1.x29 |
Công thức này cho thấy cách NextPDF kết xuất một tập con HTML và CSS được hỗ trợ. Nó không khẳng định hỗ trợ đầy đủ HTML hay đầy đủ CSS. Trạng thái đã kiểm chứng của từng module nằm trong bảng hỗ trợ CSS.
Bối cảnh thương mại
Phần tiêu đề “Bối cảnh thương mại”Không áp dụng.