แพ็กเกจ Artisan มีหน้าที่สองอย่างที่เชื่อมโยงกัน คือเรนเดอร์ Hypertext Markup Language (HTML) ผ่าน Chrome และนำเข้าหน้า Portable Document Format (PDF) ที่ได้เข้าสู่เอกสาร NextPDF เมื่อแก้จุดบกพร่อง ให้แยกขอบเขตของ Chrome ตัวแยกวิเคราะห์ และตัวนำเข้าออกจากกัน
ใช้คู่มือนี้เมื่อเขียนการผสานรวมตัวเรนเดอร์ เวิร์กเกอร์ที่ทำงานยาวนาน การวินิจฉัยตัวแยกวิเคราะห์ หรือการทดสอบสำหรับ nextpdf/artisan
| เลเยอร์ | ดูแลโดย | ความรับผิดชอบ | อย่าใส่ไว้ที่นี่ |
|---|
| แอปพลิเคชัน | แอปพลิเคชัน | อนุญาตให้สร้าง HTML และเลือกการกำหนดค่าตัวเรนเดอร์ | การจัดการกระบวนการของเบราว์เซอร์ |
| นโยบาย HTML | แอปพลิเคชันและแพ็กเกจ | ปฏิเสธ HTML ที่ไม่ปลอดภัยหรือมีขนาดใหญ่เกินไปก่อนเรนเดอร์ | การให้สิทธิ์ผู้เช่าหรือการตัดสินใจทางธุรกิจ |
| ตัวเรนเดอร์ Chrome | nextpdf/artisan | เรนเดอร์ HTML ให้เป็น PDF เดี่ยวที่ Chrome สร้างขึ้น | การซ่อม PDF ทั่วไปหรือการแก้ไข PDF ตามอำเภอใจ |
| ตัวแยกวิเคราะห์/ตัวนำเข้า | nextpdf/artisan | แยกวิเคราะห์ PDF ที่เรนเดอร์แล้วและนำเข้าหนึ่งหน้าเป็น form XObject | การตรวจสอบความสอดคล้องของ PDF อย่างครบถ้วน |
| เอนจินหลัก | nextpdf/nextpdf | วางอ็อบเจกต์ form ที่นำเข้าและเขียนเอกสารสุดท้าย | วงจรชีวิตของ Chrome DevTools Protocol (CDP) |
| ขั้นตอน | พฤติกรรม | การดำเนินการของนักพัฒนา |
|---|
| การสร้างการกำหนดค่า | ChromeRendererConfig กำหนดไบนารี ค่าหมดเวลา Cascading Style Sheets (CSS) ขนาดอินพุต และพฤติกรรมแซนด์บ็อกซ์ | ใช้การกำหนดค่าเฉพาะสภาพแวดล้อมแทนการฮาร์ดโค้ดค่าที่คาดเดาจากขณะทำงาน |
| การสร้างตัวเรนเดอร์ | ChromeHtmlRenderer เป็นเจ้าของ BrowserPool หนึ่งตัว | นำตัวเรนเดอร์มาใช้ซ้ำภายในเวิร์กเกอร์ จากนั้นปิดตัวเรนเดอร์ระหว่างการปิดระบบ |
| การตรวจสอบ HTML | นโยบายความปลอดภัยตรวจสอบขนาดและห่อหุ้มเอกสารด้วย CSS เริ่มต้น | ตรวจสอบการให้สิทธิ์ของผู้เรียกก่อนขั้นตอนนี้ |
| การพิมพ์ของ Chrome | CDP เรนเดอร์ PDF แบบเดี่ยว | บล็อกทรัพยากรภายนอกไว้เสมอ เว้นแต่นโยบายที่ผ่านการตรวจสอบจะอนุญาตให้ใช้ได้ |
| การแยกวิเคราะห์ PDF | PdfReader::parse() อ่านข้อมูล xref หน้า อ็อบเจกต์ ทรัพยากร และการปรับปรุงแก้ไข | ถือว่าความล้มเหลวของตัวแยกวิเคราะห์เป็นความล้มเหลวของการเรนเดอร์ เว้นแต่มีเป้าหมายเพื่อวินิจฉัย |
| การนำเข้าหน้า | PageImporter::import() ดึงเนื้อหาของหน้า media box ทรัพยากร และอ็อบเจกต์ที่ฝังไว้ | นำเข้าหน้า 0 เว้นแต่เวิร์กโฟลว์จะเลือกหน้าอื่นโดยเจตนา |
| เส้นทาง | วัตถุประสงค์ |
|---|
app/Pdf/Renderers/* | ตัวห่อหุ้มระดับแอปพลิเคชันรอบ ChromeHtmlRenderer |
app/Pdf/Templates/* | การเรนเดอร์เทมเพลต HTML และการแมป data transfer object (DTO) กับมุมมอง |
app/Pdf/Policies/* | นโยบายการเรนเดอร์เกี่ยวกับขนาด HTML ทรัพยากร และผู้เช่า |
tests/Pdf/Renderer/* | การทดสอบสโมกของตัวเรนเดอร์ด้วยฟิกซ์เจอร์ HTML ขนาดเล็ก |
tests/Pdf/Parser/* | ฟิกซ์เจอร์ตัวแยกวิเคราะห์สำหรับเอาต์พุตของ Chrome ที่นำเข้า |
แยกการเรนเดอร์เทมเพลตออกจากการเรนเดอร์ของเบราว์เซอร์ ส่ง HTML สุดท้ายและความกว้างของหน้าที่ทราบค่าแล้วให้ตัวเรนเดอร์
use NextPDF\Artisan\ChromeHtmlRenderer;
use NextPDF\Artisan\ChromeRendererConfig;
use NextPDF\Artisan\PageImporter;
use NextPDF\Parser\PdfReader;
$renderer = new ChromeHtmlRenderer(new ChromeRendererConfig(
$result = $renderer->render($html, widthPt: 595.28);
$reader = new PdfReader($result->getPdfData());
$form = (new PageImporter())->import($reader);
สร้างตัวเรนเดอร์หนึ่งตัวต่อกระบวนการเวิร์กเกอร์หรือต่อขอบเขตคำขอ นำกลับมาใช้ซ้ำเพื่อหลีกเลี่ยงต้นทุนจากการเริ่ม Chrome ซ้ำ ๆ ปิดตัวเรนเดอร์อย่างชัดเจนเพื่อป้องกันกระบวนการรั่วไหลระหว่างการปิดระบบเวิร์กเกอร์
final class InvoiceChromeRenderer
public function __construct(
private readonly ChromeHtmlRenderer $renderer,
public function renderInvoice(string $html): string
->render($html, widthPt: 595.28)
public function close(): void
$this->renderer->close();
ใช้ส่วนต่อประสานโปรแกรมประยุกต์ (API) ของตัวแยกวิเคราะห์เมื่อเอาต์พุตของ Chrome นำเข้าไม่สำเร็จ ทำการวินิจฉัยแบบอ่านอย่างเดียว และหลีกเลี่ยงการเปลี่ยนสถานะของตัวแยกวิเคราะห์หลังจากนำเข้าสำเร็จแล้ว
| คำถามในการวินิจฉัย | API ที่จะใช้ | สัญญาณที่คาดหวัง |
|---|
| ไฟล์แยกวิเคราะห์ได้หรือไม่ | PdfReader::parse() | โยนข้อยกเว้นสำหรับโครงสร้าง PDF ที่ไม่ถูกต้อง |
หน้า 0 มีอยู่หรือไม่ | PdfReader::getPage(0) | คืนค่าเป็น PdfObject |
| มีเนื้อหาหรือไม่ | PdfReader::getPageContentStream($page) | สตรีมเนื้อหาที่ไม่ว่างเปล่า |
| มีทรัพยากรอยู่หรือไม่ | PdfReader::getPageResources($page) | อาร์เรย์พจนานุกรมทรัพยากร |
| มีการปรับปรุงแก้ไขแบบเพิ่มหน่วยหรือไม่ | PdfReader::getRevisionCount() | จำนวนมากกว่าหนึ่ง |
| อ็อบเจกต์ใดที่ล้มเหลว | PdfTokenizer::getOffset() และบริบทของข้อยกเว้นจากตัวแยกวิเคราะห์ | ออฟเซตเป็นไบต์สำหรับย่อฟิกซ์เจอร์ |
| จุดต่อขยาย | ใช้สำหรับ | ข้อจำกัด |
|---|
ChromeRendererConfig::fromArray() | การแมปการกำหนดค่าของเฟรมเวิร์ก | ค่าทางเลือกที่ไม่รู้จักหรือมีชนิดข้อมูลผิดจะใช้ค่าเริ่มต้นแทน |
HtmlSecurityPolicyInterface | นโยบาย HTML ระดับการแยกวิเคราะห์ | ไม่ทดแทนการควบคุมการขนส่งข้อมูล กระบวนการ หรือการให้สิทธิ์ |
LoggerInterface | การวินิจฉัยการเรนเดอร์และเบราว์เซอร์ | อย่าบันทึกเนื้อหา HTML เป็นค่าเริ่มต้น |
BrowserPool | การนำกระบวนการ Chrome ที่ทำงานยาวนานกลับมาใช้ซ้ำ | ต้องปิดเมื่อมีการปิดระบบเวิร์กเกอร์ |
PageImporter | การฝังหน้าภายนอกที่แยกวิเคราะห์แล้ว | ต้องแยกวิเคราะห์รีดเดอร์ก่อน |
| คลาสของตัวแยกวิเคราะห์ | การวินิจฉัยและเอาต์พุตของ Chrome ที่นำเข้า | ไม่ใช่ชุดเครื่องมือซ่อมแซม PDF ทั่วไป |
- จำลองส่วนของ HTML ในการทดสอบการเรนเดอร์ขั้นต่ำ
- ตรวจสอบ
maxHtmlSize CSS เริ่มต้น และเส้นทางไบนารีของ Chrome
- เรนเดอร์ด้วยความกว้างคงที่เป็นพอยต์
- แยกวิเคราะห์ไบต์ PDF ที่คืนค่ามาด้วย
PdfReader::parse()
- นำเข้าหน้า
0 เว้นแต่เวิร์กโฟลว์จะเลือกหน้าอื่นโดยเจตนา
- เพิ่มการทดสอบฟิกซ์เจอร์สำหรับ HTML ที่เล็กที่สุดซึ่งจำลองความล้มเหลวแต่ละกรณีได้
- ปิดตัวเรนเดอร์ในฮุกการปิดระบบเวิร์กเกอร์
| ความล้มเหลว | ควรจัดการที่ใด | การตอบสนองที่แนะนำ |
|---|
| ไม่พบไบนารีของ Chrome | การตรวจสอบการปรับใช้และเส้นทางการสร้างตัวเรนเดอร์ | ทำให้ความพร้อมล้มเหลวก่อนรับทราฟฟิกการเรนเดอร์ |
| HTML ที่มีขนาดใหญ่เกินไป | นโยบาย HTML | ปฏิเสธก่อนเริ่ม Chrome |
| การหมดเวลาของเบราว์เซอร์ | ขอบเขตของตัวเรนเดอร์ | ทำให้การเรนเดอร์ล้มเหลว และบันทึกชื่อเทมเพลต ขนาด ความกว้าง และค่าหมดเวลา |
| ความล้มเหลวของตัวแยกวิเคราะห์ | ขอบเขตการนำเข้า | จัดเก็บฟิกซ์เจอร์ขนาดเล็กที่ผ่านการล้างข้อมูลเพื่อแก้จุดบกพร่องเมื่อนโยบายอนุญาต |
| การรั่วไหลของกระบวนการเบราว์เซอร์ | วงจรชีวิตของเวิร์กเกอร์ | ปิดเมื่อปิดระบบและเริ่มใหม่หลังจากจำนวนการเรนเดอร์ที่ควบคุมไว้ |
| ประเด็นที่เกี่ยวข้อง | ค่าเริ่มต้น | เมื่อใดควรแทนที่ค่า |
|---|
| ค่าหมดเวลาในการเรนเดอร์ | 30 วินาที | เพิ่มค่าเฉพาะสำหรับเอกสารที่วัดผลแล้วและมีขอบเขตจำกัดเท่านั้น |
| ขนาด HTML สูงสุด | 5,000,000 ไบต์ | ลดค่าลงสำหรับเอนด์พอยต์สาธารณะ |
| แซนด์บ็อกซ์ | เปิดใช้งาน | ปิดใช้งานเฉพาะเมื่อข้อจำกัดของคอนเทนเนอร์บังคับให้ทำเท่านั้น และโฮสต์ถูกแยกออกมาต่างหาก |
| ความสูง | อัตโนมัติเมื่อ heightPt <= 0 | ใช้ความสูงคงที่สำหรับสัญญาเค้าโครงที่เข้มงวด |
| ทรัพยากรภายนอก | ถูกบล็อกโดยนโยบายของตัวเรนเดอร์ | อนุญาตผ่านนโยบายทรัพยากรที่ผ่านการตรวจสอบเท่านั้น |
- การทดสอบการเรนเดอร์ครอบคลุม HTML และ CSS ที่เป็นตัวแทน
- การทดสอบความปลอดภัยครอบคลุม HTML ที่มีขนาดใหญ่เกินไปและความพยายามใช้ทรัพยากรที่ถูกบล็อก
- การทดสอบการนำเข้ายืนยันว่าอ็อบเจกต์ form ที่คืนค่ามามีเนื้อหา media box และทรัพยากร
- การทดสอบตัวแยกวิเคราะห์ครอบคลุมตาราง cross-reference (xref) สตรีม xref สตรีมอ็อบเจกต์ และกรณีฟิกซ์เจอร์ที่ผิดรูปแบบ
- การทดสอบเวิร์กเกอร์เรียก
close() และยืนยันว่าไม่มีกระบวนการเบราว์เซอร์เหลืออยู่
- การทดสอบประสิทธิภาพบันทึกเวลาการเรนเดอร์ตามเทมเพลตและขนาดเนื้อหา