跳转到内容

线性化:Fast Web View 输出

线性化 PDF——也就是 Fast Web View——采用一种布局,让读取端能在文件其余部分尚未抵达前先显示第一页。第一页的对象、对应的交叉引用子区段,以及用于定位其他每一页的提示表,都位于文件前段。NextPDF 以确定性方式输出这套布局:相同文档在每一台主机上都会生成相同字节,且结果可通过 qpdf --check-linearization 检查。

线性化是一项 Core 功能。你在 Document 上选择启用;引擎会处理三趟布局、线性化参数字典与提示表。读取端的 LinearizationView 会解析已完成文件的线性化字典,让传输层(transport)无需重新实现这套格式即可规划传递。

Terminal window
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

examples/linearization/enable.php
<?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 output

withLinearization() 与其他 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 前段中的线性化参数字典。它是传输层规划传递时唯一受支持的绑定点;调用方永远不需要自行重新实现字典解析。

examples/linearization/inspect.php
<?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;
}
类型种类主要成员稳定性自版本
DocumentenableLinearization(): staticuseLegacyLinearizer(): static稳定3.2.0
ConfigwithLinearization(bool $linearize = true): self稳定6.1.0
LinearizationViewfromPdf(string): selflengthMatches(int): bool、公开的只读字典字段稳定3.2.0

enableLinearization() 会在加密或 PAdES 签名已配置时抛出 InvalidConfigException。对于不包含任何线性化字典的文档,LinearizationView::fromPdf() 会返回一个 isLinearized 标志为 false 的视图。

  • 线性化文档无法同时被加密,也无法以 PAdES 签名。每次构建只能择一。
  • 旧版 v1 后端会输出不符规范的 Annex F 参数,只是为了与较旧的输出维持字节兼容而存在。规范守卫是针对 v2 执行的。
  • Fast Web View 是一种传递优化,而不是安全或验证功能;它不会改变已渲染的页面内容。