Artisan Chrome işleyicisiyle HTML'i PDF'ye dönüştürün
Genel bakış
“Genel bakış” başlıklı bölümArtisan köprüsü, HTML’i başsız bir Chrome süreciyle işler ve ardından sonucu bir NextPDF belgesine vektör Form XObject’i olarak içe aktarır. Metin rasterleştirilmek yerine seçilebilir ve aranabilir kalır. Bunun için bir ChromeRendererConfig eklersiniz, belgede writeHtmlChrome() çağırırsınız veya doğrudan ChromeHtmlRenderer kullanıp yerleşimi Chrome’a bırakırsınız. Bu kılavuz; işleme çağrısını, ağ yalıtımını, sayfa boyutlandırmasını, içerik yüksekliğini ve bir işçi için uzun ömürlü işleyicinin yaşam döngüsünü kapsar.
Önce ön koşulları karşılayın:
- NextPDF core ve
nextpdf/artisankuruludur. - Bir Chrome veya Chromium ikili dosyası kurulu olmalıdır ve işçi kullanıcı bunu başsız çalıştırabilmelidir. Başlamadan önce bunu
chromium --headless --dump-dom about:blankile doğrulayın. Ayrıca bakınız bölümünde bağlantısı verilen Chrome işleyici kurulum sayfası, ikili dosya sağlamayı ve kapsayıcı sanal alanı kararını kapsar.
Bu kılavuz, uygulamanızla aynı ortamda bir Chrome süreci çalıştırabildiğinizi varsayar. İlk çalıştırılabilir örnek için Artisan hızlı başlangıç sayfasına bakın.
Kurulum
“Kurulum” başlıklı bölümKöprüyü core ile birlikte kurun.
composer require nextpdf/artisanİşçi kullanıcının çalıştırabileceği bir Chrome veya Chromium derlemesi kurun. Debian veya Ubuntu’da dağıtım paketini kullanın.
apt-get install -y chromiumİkili dosyanın işçi kullanıcıyla başsız çalışabildiğini doğrulayın.
chromium --headless --dump-dom about:blankBoş bir belge nesnesi modeli (DOM) çıktısı ve 0 çıkış kodu, ikili dosyanın ve paylaşılan kitaplıklarının mevcut olduğu anlamına gelir. Sıfır olmayan çıkış kodu, köprünün ChromeRenderException olarak bildirdiği hatanın aynısıdır. Önce bunu burada düzeltin.
Kavramsal genel bakış
“Kavramsal genel bakış” başlıklı bölümwriteHtmlChrome(), NextPDF core’daki Document üzerinde bir yöntemdir. Girdiyi doğrular, Artisan işleyicisini çözer, HTML’i Chrome DevTools Protocol (CDP) üzerinden Chrome’a gönderir, dönen PDF’yi ayrıştırır ve 0. sayfayı geçerli imleç konumuna bir Form XObject’i olarak gömer. Chrome, PHP işçisinin bir alt süreci olarak çalışır. Köprü, ayrı bir Chrome sürecine bir hata ayıklama bağlantı noktası üzerinden bağlanmak yerine Chrome’u CDP üzerinden yönetir; bu nedenle açığa çıkarılacak veya kimlik doğrulaması yapılacak bir ağ uç noktası yoktur.
Köprü, varsayılan olarak reddet yaklaşımıyla çalışır. Her işleme, tüm kaynak kökenlerini reddeden (default-src 'none') ve yalnızca satır içi görüntülere izin veren (img-src data:) bir Content-Security-Policy kullanır. Köprü ayrıca her alt kaynak URL’sini CDP taşıma katmanında Network.setBlockedURLs(['*']) ile engeller. Sonuç olarak HTML’inizdeki uzak bir görüntü, stil sayfası, yazı tipi, betik veya iframe yüklenmez. Her varlığı bir data: URI’si olarak satır içine alın. Köprü, güvenilmez olabilecek HTML’i işlerken sunucu tarafı istek sahteciliği (SSRF) riskini bu şekilde ele alır ve bu, yapılandırmadan bağımsız olarak uygulanır.
Sayfa boyutu modelinin iki kipi vardır. Hem genişliği hem de yüksekliği PDF noktası cinsinden verdiğinizde, Chrome tam olarak o kağıt boyutuna yazdırır. Yükseklik atlandığında veya null olduğunda, köprü işlenen içerik yüksekliğini Chrome’da ölçer, noktaya dönüştürür ve yaklaşık 14.4 noktalık küçük bir yeniden akış güvenlik tamponu ekler. Bu, printToPDF çıktısının yalnızca 0. sayfayı içe aktaran içe aktarıcının kırpacağı ikinci bir sayfaya taşmasını önler.
API yüzeyi
“API yüzeyi” başlıklı bölüm// On a NextPDF core Document (the HasTextOutput concern):writeHtmlChrome(string $html, ?float $width = null, ?float $height = null): static
// The standalone renderer:new ChromeHtmlRenderer(ChromeRendererConfig $config, ?LoggerInterface $logger = null)ChromeHtmlRenderer::render(string $html, float $widthPt, float $heightPt = 0.0): ChromeRenderResultChromeHtmlRenderer::close(): void
// The configuration value object (final readonly):new ChromeRendererConfig( ?string $chromeBinaryPath = null, int $renderTimeout = 30, string $defaultCss = '', int $maxHtmlSize = 5_000_000, bool $noSandbox = false,)ChromeRendererConfig::fromArray(array $config): selfChromeRendererConfig tek yapılandırma yüzeyidir. Değişmezdir; bu nedenle bir değeri değiştirmek için yeni bir örnek oluşturun. ChromeRenderResult::getPdfData() PDF baytlarını döndürür. Ayrıca bakınız bölümünde bağlantısı verilen Artisan yapılandırma sayfası, eksiksiz seçenek başvurusunu ve sabit Chrome başlatma bayraklarını listeler.
Kod örneği — hızlı başlangıç
“Kod örneği — hızlı başlangıç” başlıklı bölümYapılandırmayı bir belgeye ekleyin, güvenilir HTML’i işleyin ve kaydedin.
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Artisan\ChromeRendererConfig;use NextPDF\Core\Document;
$config = new ChromeRendererConfig( chromeBinaryPath: '/usr/bin/chromium',);
$document = Document::createStandalone();$document->setChromeRendererConfig($config);$document->addPage();
$document->writeHtmlChrome(' <div style="display: flex; gap: 20px; font-family: sans-serif;"> <div style="flex: 1; background: #f0f0f0; padding: 24px;"> <h2>Revenue</h2> <p style="font-size: 2em; color: #2563eb;">$124,500</p> </div> <div style="flex: 1; background: #f0f0f0; padding: 24px;"> <h2>Orders</h2> <p style="font-size: 2em; color: #16a34a;">1,847</p> </div> </div>');
$document->save('/tmp/report.pdf');Chrome, flex yerleşimini işler; sayfa raster görüntü değil, vektör Form XObject’i olarak gömüldüğü için sayılar çıktıda seçilebilir kalır. Sabit bir A4 sayfasına sığdırmak için genişliği ve yüksekliği nokta cinsinden geçirin.
$document->writeHtmlChrome($html, width: 595.28, height: 841.89);Kod örneği — üretim
“Kod örneği — üretim” başlıklı bölümÜretimde işçi başına bir işleyici oluşturun, bir PSR-3 günlükçüsü enjekte edin, iki ayrı özel durum türünü ayrı ayrı yakalayın ve kapatma sırasında Chrome sürecini belirlenimci biçimde serbest bırakın.
<?php
declare(strict_types=1);
use NextPDF\Artisan\ChromeHtmlRenderer;use NextPDF\Artisan\ChromeRendererConfig;use NextPDF\Artisan\Exception\ChromeNotAvailableException;use NextPDF\Artisan\Exception\ChromeRenderException;use Psr\Log\LoggerInterface;
final class ReportRenderer{ private ChromeHtmlRenderer $renderer;
public function __construct(LoggerInterface $logger) { $config = ChromeRendererConfig::fromArray([ 'chrome_binary' => getenv('CHROME_BINARY') ?: null, 'render_timeout' => 45, 'max_html_size' => 2_000_000, 'no_sandbox' => (bool) getenv('CHROME_NO_SANDBOX'), ]);
$this->renderer = new ChromeHtmlRenderer($config, $logger); }
public function render(string $html, float $widthPt, float $heightPt = 0.0): string { try { return $this->renderer->render($html, $widthPt, $heightPt)->getPdfData(); } catch (ChromeNotAvailableException $exception) { // Deployment fault: the Chrome runtime is missing. Page on-call. throw $exception; } catch (ChromeRenderException $exception) { // Render-time fault: timeout, crash, or empty output. Retryable once. throw $exception; } }
public function shutdown(): void { $this->renderer->close(); }}İşleyiciyi bir kez oluşturun, ardından yeniden kullanın. Alttaki tarayıcı havuzu bir Chrome sürecini canlı tutar ve bellek kullanımındaki artışı sınırlamak için onu her 100 işlemede bir yeniden başlatır. İki yakalama kolu, eksik çalışma zamanı gibi bir dağıtım hatasını, bir kez yeniden deneyebileceğiniz bir işleme zamanı hatasından ayırır. Hiçbir yakalama bloğu boş değildir. İşçi kapandığında, yıkıcıya güvenmek yerine Chrome sürecini serbest bırakmak için shutdown() çağırın.
Snake-case anahtarları kullanmak için yapılandırmayı bir çerçeve yapılandırma dizisinden oluşturun ve ikili dosya seçiminin belirlenimci olması için üretimde chromeBinaryPath değerini sabitleyin.
Sınır durumları ve tuzaklar
“Sınır durumları ve tuzaklar” başlıklı bölüm- Boş HTML işlem yapmaz.
writeHtmlChrome('')belgeyi değişmeden döndürür. - Henüz sayfa yok. Belgenin sayfası yoksa,
writeHtmlChrome()işlemeden önce bir sayfa ekler. - Uzak varlıklar yüklenmez — tasarım gereği.
<img src="https://...">boş olarak işlenir. Her varlığı birdata:URI’si olarak satır içine alın. Bu, bir kusur değil, ağ yalıtımı yaklaşımıdır. - Yalnızca 0. sayfa içe aktarılır. Otomatik sığdırma yüksekliği, tek bir sayfa üretilecek şekilde yeniden akış tamponunu ekler. Açık yükseklik kullanıldığında hiçbir tampon eklenmez ve çıktı tam olarak istenen kağıt boyutuyla eşleşir; bu nedenle yüksekliği içeriğinize sığacak şekilde boyutlandırın.
- Köprü eksik.
nextpdf/artisankurulu değilse, core ölümcül hata yerine bir yerleşim özel durumu yükseltir.chrome-php/chromekitaplığı yoksa, köprü kurulum komutuyla birlikteChromeNotAvailableExceptionyükseltir. defaultCssve</style>.</style>içindeki herhangi birdefaultCssdizisi, stil kaçışı savunması olarak enjeksiyondan önce çıkarılır. CSS şablonu oluşturuyorsanız buna göre plan yapın.
Performans
“Performans” başlıklı bölümİlk işleme, Chrome’u başlatma ve yerleşim maliyetini taşır. Sonraki işlemeler canlı Chrome sürecini yeniden kullanır; bu nedenle başlatma maliyetini nadiren üstlenir. İşçi başına bir işleyici oluşturun ve onu yeniden kullanın. İstek başına bir tane oluşturmayın. Köprü, belleği sınırlamak için Chrome sürecini yeniden başlattığında, her 100. işlemede bir gecikme artışı bekleyin. Bunu tekil bir olay gibi ele almak yerine gecikme hedeflerinizde hesaba katın. Güvenilmez girdiyle ulaşılabilen herhangi bir yolda renderTimeout değerini bir üst akış istek bütçesiyle eşleştirin.
Güvenlik notları
“Güvenlik notları” başlıklı bölüm- Birincil denetim ağ yalıtımıdır. Köprü, giden alt kaynak getirmeye kesinlikle izin vermez: CSP
default-src 'none'artı her URL’nin CDP taşıma düzeyinde engellenmesi. Hiçbirine ihtiyaç duymadığı için bir etki alanı izin listesi uygulamaz. Varlıklarıdata:URI’leri olarak satır içine alın. - Girdi, Chrome ile iletişime geçilmeden önce sınırlandırılır. Köprü;
maxHtmlSizedeğerini aşan HTML’i (varsayılan 5 MB), aşırı büyük bir base64 data URI’sini (bir açma bombası koruması) ve bir iç uç noktaya gezinmeye yönlendirebilecek herhangi bir<meta http-equiv="refresh">etiketini reddeder. Bilinen bir iş yükü daha fazlasına ihtiyaç duymadıkçamaxHtmlSizedeğerini varsayılanda tutun. Bu değeri yükseltmek, kaynak tükenmesi yüzeyini genişletir. - Chrome sanal alanı ayrı bir denetimdir.
noSandbox: trueayarlamak, Chrome’u--no-sandboxile başlatır; bu da Chrome süreç yalıtımını kaldırır. Bu, kozmetik bir bayrak değil, kapsama düzeyinde gerçek bir azalmadır. Kapsayıcıların dışında onufalsebırakın. Kapsayıcı sanal alanı başlatılamadığında, Chrome’u kısıtlanmış bir kapsayıcıda root olmayan bir kullanıcı olarak çalıştırın ve dağıtımı, girdi üzerinde daha yüksek güven gerektiren bir durum olarak ele alın. - Günlükler yalnızca meta veri taşır. Bir PSR-3 günlükçüsü enjekte edin. Köprü; bayt uzunluklarını, boyutları ve yaşam döngüsü olaylarını günlüğe kaydeder, asla HTML’i, PDF baytlarını veya çıkarılan metni kaydetmez.
- Bir Chrome uzaktan hata ayıklama bağlantı noktasını asla açığa çıkarmayın. Köprü böyle bir bağlantı noktası kullanmaz ve açık bir CDP bağlantı noktası, kimliği doğrulanmamış bir denetim kanalıdır.
SSRF savunması, açık sanal alan sınırı ve hata kipi kataloğu dahil olmak üzere tam tehdit modeli, Ayrıca bakınız bölümünde bağlantısı verilen Artisan güvenlik ve operasyonlar sayfasında yer alır. Bu sayfa, ilgili OWASP, CWE ve NIST maddelerine bağlanır.
Uygunluk
“Uygunluk” başlıklı bölümBu kılavuz, kendine ait normatif bir standart iddiasında bulunmaz. Üst akış Artisan güvenlik ve operasyonlar sayfası, köprünün ağ, yalıtım ve kaynak tükenmesi denetimlerini OWASP ASVS’ye, CWE Top 25’e (SSRF / denetimsiz kaynak tüketimi) ve NIST SP 800-53 SC-7’ye eşler. Bu Cookbook sayfası kullanımı yeniden ifade eder ve normatif atıfları o sayfaya bırakır. Köprü hiçbir şifreleme işlemi gerçekleştirmez; imzalama ve şifreleme, core veya ticari sürüm konularıdır ve Artisan’dan etkilenmez.
Ayrıca bakınız
“Ayrıca bakınız” başlıklı bölüm- Cloudflare ile uç noktada işleme — HTML’i yerel yedekle birlikte uç noktada işleyin.
- Artisan hızlı başlangıç — en küçük ilk işleme örneği.
- Chrome işleyici kurulumu — ikili dosyayı sağlayın, kapsayıcı sanal alanı kararını verin ve bir sağlık yoklaması ayarlayın.
- Artisan güvenlik ve operasyonlar — ağ yalıtımı modeli, sanal alan sınırı ve hata kipleri.