线性化:Fast Web View 输出
线性化 PDF——也就是 Fast Web View——采用一种布局,让读取端能在文件其余部分尚未抵达前先显示第一页。第一页的对象、对应的交叉引用子区段,以及用于定位其他每一页的提示表,都位于文件前段。NextPDF 以确定性方式输出这套布局:相同文档在每一台主机上都会生成相同字节,且结果可通过 qpdf --check-linearization 检查。
线性化是一项 Core 功能。你在 Document 上选择启用;引擎会处理三趟布局、线性化参数字典与提示表。读取端的 LinearizationView 会解析已完成文件的线性化字典,让传输层(transport)无需重新实现这套格式即可规划传递。
composer require nextpdf/core:^3概念总览
标题为“概念总览”的章节标准 PDF 把交叉引用表放在文件末尾,因此读取端必须先取得文件尾段,才能解析(resolve)任何对象。线性化 PDF 会把文件重新排列为两个部分。第一部分包含线性化参数字典、第一页,以及页面偏移提示表。第二部分包含其余各页。支持 Fast Web View 的读取端可以先从第一部分渲染第一页,再利用提示表,在字节持续抵达的同时直接定位到后续任一页面——ISO 32000-2 Annex F。
NextPDF 提供两种后端(backend)。默认的 v2 后端是一个三趟线性化器,会生成符合 ISO 32000-2 Annex F 的输出,包含符合规范的页面偏移提示表,且其 /L 长度恰好等于文件的精确字节长度。保留 v1 旧版后端,是为了与 v2 之前生成的文档维持字节兼容;它会输出不符规范的 Annex F 参数,且只会在主动选择时启用。新的开发工作应使用默认后端。
确定性是一项硬性保证。文件标识符从内容摘要推导而来,而非取自随机来源,因此 enableLinearization() 是文档的纯函数。正是这一点让黄金字节测试(golden byte tests)能够固定输出,也让下游能实现内容寻址缓存或稳定的 ETag。
启用线性化
标题为“启用线性化”的章节<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Core\Document;
$document = Document::createStandalone();$document->writeHtml('<h1>Quarterly report</h1>');$document->enableLinearization();
// Deterministic: the same document always produces the same bytes.$pdf = $document->output();默认后端是 v2。若要选择启用旧版 v1 后端,请先调用 useLegacyLinearizer()(调用顺序不限):
$document->useLegacyLinearizer();$document->enableLinearization();从配置启用
标题为“从配置启用”的章节你也可以通过 Config 以声明式方式选择启用。这项设置会在构建文档时应用,适合那些在前期就固定好传递格式、而不想在每份文档上逐一调用方法的管线:
use NextPDF\Core\Config;use NextPDF\Core\Document;
$config = (new Config())->withLinearization();$document = Document::createStandalone($config);$document->writeHtml('<h1>Quarterly report</h1>');
$pdf = $document->output(); // linearized outputwithLinearization() 与其他 Config 选项一样,默认关闭。传入 false 可让这个选择更明确。以这种方式构建的文档会走相同的 enableLinearization() 路径,因此下方的规范守卫同样适用。
规范交互关系
标题为“规范交互关系”的章节线性化可以与标记式(tagged)及归档(archival)配置文件组合使用,但与会使前置提示表或字节范围签名失效的功能互斥。
| 功能 | 交互关系 |
|---|---|
| PDF/A、PDF/UA 配置文件 | 可组合。v2 会保留对象编号,因此结构与标签引用仍然有效。 |
| 加密(AES-256、AES-GCM、公钥) | 互斥。 提示流(hint stream)会以明文输出,因此引擎会拒绝这一组合。 |
| PAdES 签名 | 互斥。 重新线性化会改写字节偏移,并破坏签名的 /ByteRange。 |
| 增量更新 | 在单次构建中互斥。 |
这道守卫是双向的,且与调用顺序无关:对已标记为线性化的文档请求加密(或签名)会抛出异常,而对已加密(或已签名)的文档标记线性化也会抛出异常。两种情况都会抛出 InvalidConfigException。
use NextPDF\Exception\InvalidConfigException;
$document->setEncryption('user-pw', 'owner-pw'); // (userPassword, ownerPassword)
try { $document->enableLinearization(); // rejected — encryption is already configured} catch (InvalidConfigException $e) { // Linearization and encryption cannot be combined on one document.}读取线性化文件
标题为“读取线性化文件”的章节LinearizationView 会解析已完成 PDF 前段中的线性化参数字典。它是传输层规划传递时唯一受支持的绑定点;调用方永远不需要自行重新实现字典解析。
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Writer\Linearization\LinearizationView;
$view = LinearizationView::fromPdf($pdf);
if ($view->isLinearized) { // Plan, e.g., a first-page byte range from the parsed dictionary fields: // file length, first-page object number, main cross-reference offset, // hint-table offset and length, first-page end offset, page count. $firstPageEnd = $view->firstPageEndOffset;}API 接口
标题为“API 接口”的章节| 类型 | 种类 | 主要成员 | 稳定性 | 自版本 |
|---|---|---|---|---|
Document | 类 | enableLinearization(): static、useLegacyLinearizer(): static | 稳定 | 3.2.0 |
Config | 类 | withLinearization(bool $linearize = true): self | 稳定 | 6.1.0 |
LinearizationView | 类 | fromPdf(string): self、lengthMatches(int): bool、公开的只读字典字段 | 稳定 | 3.2.0 |
enableLinearization() 会在加密或 PAdES 签名已配置时抛出 InvalidConfigException。对于不包含任何线性化字典的文档,LinearizationView::fromPdf() 会返回一个 isLinearized 标志为 false 的视图。
- 线性化文档无法同时被加密,也无法以 PAdES 签名。每次构建只能择一。
- 旧版 v1 后端会输出不符规范的 Annex F 参数,只是为了与较旧的输出维持字节兼容而存在。规范守卫是针对 v2 执行的。
- Fast Web View 是一种传递优化,而不是安全或验证功能;它不会改变已渲染的页面内容。