PDF 解析器¶
PdfParser 提供低層級的 PDF 結構解析能力,讀取現有 PDF 文件並提取頁面、物件與元資料。解析器嚴格遵循 PDF 2.0(ISO 32000-2:2020)規格,同時向下相容 PDF 1.4–1.7 的 xref 格式。
PHP Compatibility
This example uses PHP 8.5 syntax. If your environment runs PHP 8.1 or 7.4, use NextPDF Backport for a backward-compatible build.
解析器的主要使用場景是配合 PageImport 將既有 PDF 頁面以 Form XObject 形式嵌入新文件。
開啟 PDF 文件¶
<?php
declare(strict_types=1);
use NextPDF\Artisan\PdfParser;
use NextPDF\Artisan\ValueObjects\ParsedPage;
// 從檔案路徑開啟
$parser = PdfParser::fromFile('/path/to/document.pdf');
// 從 bytes 字串開啟(適用於記憶體中的 PDF)
$parser = PdfParser::fromBytes($pdfBytes);
// 從 PHP stream resource 開啟(適用於大型檔案串流讀取)
$parser = PdfParser::fromStream($fileHandle);
提取頁面¶
$parser = PdfParser::fromFile('/path/to/source.pdf');
// 取得所有頁面(延遲載入)
/** @var list<ParsedPage> $pages */
$pages = $parser->pages();
// 取得單一頁面(zero-based index)
$firstPage = $parser->page(index: 0);
// 取得頁數
$count = $parser->pageCount(); // positive-int
xref 表解析¶
PDF 的交叉參考表(cross-reference table)是定位文件內所有物件的索引結構。PdfParser 支援以下三種 xref 格式:
| 格式 | PDF 版本 | 說明 |
|---|---|---|
| 傳統 xref table | PDF 1.0+ | 固定寬度 ASCII 格式 |
| xref stream | PDF 1.5+ | 壓縮二進位格式(通常 FlateDecode) |
| 混合 xref | PDF 1.5+ | 傳統 table + cross-reference stream 並存 |
// 取得 xref 資訊(除錯用途)
$xref = $parser->xrefTable();
$objectCount = $xref->count(); // 文件物件總數
$isCompressed = $xref->isStream(); // 是否為壓縮格式
FlateDecode 解壓縮¶
PDF 物件流與內容流通常以 FlateDecode(zlib)壓縮。解析器自動處理解壓縮,無需手動操作:
// 取得頁面的原始內容串流(已自動解壓)
$contentStream = $firstPage->contentStream(); // string
// 取得頁面資源字典
$resources = $firstPage->resources();
$fonts = $resources->fonts(); // array<string, PdfFont>
$images = $resources->images(); // array<string, PdfImage>
支援的串流 Filter:
| Filter | 說明 |
|---|---|
FlateDecode | zlib/deflate 壓縮(最常見) |
ASCIIHexDecode | ASCII 十六進位編碼 |
ASCII85Decode | ASCII Base-85 編碼 |
LZWDecode | LZW 壓縮(PDF 1.x 舊格式) |
注意:
CCITTFaxDecode、JBIG2Decode等影像專用 Filter 僅在影像物件中支援,不適用於內容串流。
物件流(Object Streams)¶
PDF 1.5+ 引入物件流(Object Streams,類型 /ObjStm),將多個 PDF 物件壓縮儲存於單一串流中。PdfParser 完整支援此格式:
// 直接存取任意 PDF 物件(自動處理物件流解壓)
$catalog = $parser->object(objectNumber: 1, generation: 0);
$pageTree = $parser->object(objectNumber: 2, generation: 0);
// 枚舉文件中的所有物件流
$objStreams = $parser->objectStreams(); // list<ObjectStream>
foreach ($objStreams as $stream) {
$containedCount = $stream->count(); // 此串流包含的物件數
}
元資料提取¶
$meta = $parser->metadata();
$title = $meta->title(); // ?non-empty-string
$author = $meta->author(); // ?non-empty-string
$version = $meta->pdfVersion(); // e.g. '2.0', '1.7'
$pageSize = $parser->page(0)->mediaBox(); // PageSize Value Object
加密 PDF 處理¶
use NextPDF\Artisan\Config\DecryptionConfig;
$parser = PdfParser::fromFile(
path: '/path/to/encrypted.pdf',
decryption: DecryptionConfig::withUserPassword('user-pass'),
);
例外處理¶
| 例外類別 | 觸發條件 |
|---|---|
PdfParseException | 無效的 PDF 結構、魔術位元組錯誤 |
XrefCorruptedException | xref table 損壞或遺失 |
FilterDecodeException | FlateDecode 解壓縮失敗 |
EncryptedPdfException | 需要密碼但未提供 |
UnsupportedFilterException | 遇到不支援的 Filter 類型 |
參見¶
- Artisan 套件總覽 — ChromeRenderer、BrowserPool 概覽
- 頁面匯入 — 使用 ParsedPage 建立 Form XObject
- Chrome 渲染器 — 從 HTML 生成可供解析的 PDF