高级功能
本页涵盖 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 | 渲染超时 |
CdpException | CDP WebSocket 通信失败 |
FileNotFoundException | loadFile() 指定的文件不存在 |
MergeException | PDF 合并过程中发生错误 |