Skip to content

進階功能

本頁涵蓋 Artisan 套件的進階類別:PDF 合併、樣式注入、截圖擷取,以及 Chrome 程序管理與錯誤處理。

PDF 合併(PdfMerger)

PdfMerger 將多份 PDF 檔案合併為單一文件,支援檔案路徑與二進位字串兩種輸入方式:

php
use Yeeefang\TcpdfNext\Artisan\PdfMerger;

PdfMerger::create()
    ->add('/path/to/cover.pdf')
    ->add('/path/to/chapter1.pdf')
    ->add('/path/to/chapter2.pdf')
    ->save('/path/to/merged.pdf');

從二進位字串合併

搭配 HtmlRenderer::toString() 使用,可在記憶體中完成渲染與合併,無需寫入暫存檔案:

php
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;
use Yeeefang\TcpdfNext\Artisan\PdfMerger;

$renderer = HtmlRenderer::create();

$cover   = $renderer->loadHtml($coverHtml)->toString();
$content = $renderer->loadHtml($contentHtml)->toString();

PdfMerger::create()
    ->addBinary($cover)
    ->addBinary($content)
    ->save('/path/to/final.pdf');

樣式注入(StyleInjector)

StyleInjector 在 Chrome 渲染之前,將額外的 CSS 注入到 HTML 中。適用於在不修改模板的情況下覆寫樣式:

php
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;
use Yeeefang\TcpdfNext\Artisan\StyleInjector;

$injector = StyleInjector::create()
    ->add('body { font-family: "Noto Sans TC", sans-serif; }')
    ->add('@page { size: A4 landscape; }')
    ->addFile('/path/to/print-overrides.css');

HtmlRenderer::create()
    ->withStyleInjector($injector)
    ->loadUrl('https://app.example.com/dashboard')
    ->save('/tmp/dashboard.pdf');

TIP

注入的樣式會被包裹在 <style> 標籤中並插入到 <head> 的最末端,因此在層疊順序中具有最高優先權。

截圖擷取(ScreenshotCapture)

ScreenshotCapture 將 HTML 渲染為圖片而非 PDF,支援 PNG 與 JPEG 格式:

php
use Yeeefang\TcpdfNext\Artisan\ScreenshotCapture;

// 全頁截圖
ScreenshotCapture::create()
    ->loadUrl('https://example.com')
    ->fullPage()
    ->format('png')
    ->save('/tmp/screenshot.png');

// 指定視窗大小與 JPEG 品質
ScreenshotCapture::create()
    ->loadHtml($html)
    ->viewport(width: 1280, height: 720)
    ->format('jpeg')
    ->quality(85)
    ->save('/tmp/preview.jpg');

裁切特定區域

透過 clip() 只擷取頁面中的特定矩形區域:

php
ScreenshotCapture::create()
    ->loadUrl('https://example.com')
    ->clip(x: 0, y: 0, width: 800, height: 600)
    ->save('/tmp/cropped.png');

Chrome 程序設定

自訂 Chrome 路徑

php
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;

$renderer = HtmlRenderer::create(
    chromePath: '/usr/bin/google-chrome-stable',
);

額外啟動參數

透過 chromeArgs() 傳遞額外的 Chrome 命令列參數:

php
$renderer = HtmlRenderer::create()
    ->chromeArgs([
        '--no-sandbox',
        '--disable-dev-shm-usage',
        '--disable-gpu',
        '--font-render-hinting=none',
    ]);

程序重複使用

預設情況下,每次渲染都會啟動並關閉一個 Chrome 程序。如果需要批次渲染多份 PDF,可以重複使用同一個程序以提升效能:

php
$renderer = HtmlRenderer::create()->persistent();

foreach ($invoices as $invoice) {
    $renderer->loadHtml($invoice->html)
        ->save("/tmp/invoice-{$invoice->id}.pdf");
}

$renderer->close(); // 手動關閉 Chrome 程序

效能建議

策略說明
重複使用程序使用 persistent() 避免重複啟動 Chrome
避免 waitForTimeout改用 waitForSelector() 以縮短等待時間
縮小 HTML移除不必要的空白與註解
本地資源將字型與圖片放在本地,避免網路延遲
停用動畫注入 * { animation: none !important; }

錯誤處理

Artisan 定義了明確的例外類別,方便進行精確的錯誤處理:

php
use Yeeefang\TcpdfNext\Artisan\Exceptions\ChromeNotFoundException;
use Yeeefang\TcpdfNext\Artisan\Exceptions\RenderTimeoutException;
use Yeeefang\TcpdfNext\Artisan\Exceptions\CdpException;

try {
    HtmlRenderer::create()
        ->loadHtml($html)
        ->save('/tmp/output.pdf');
} catch (ChromeNotFoundException $e) {
    // Chrome 執行檔不存在或路徑錯誤
} catch (RenderTimeoutException $e) {
    // 渲染超過逾時上限
} catch (CdpException $e) {
    // CDP 通訊錯誤(如連線中斷、協定錯誤)
}
例外觸發時機
ChromeNotFoundException找不到 Chrome 執行檔
RenderTimeoutException渲染逾時
CdpExceptionCDP WebSocket 通訊失敗
FileNotFoundExceptionloadFile() 指定的檔案不存在
MergeExceptionPDF 合併過程中發生錯誤

以 LGPL-3.0-or-later 授權釋出。