跳转到内容
getnextpdf.com

Pro 版本

Document — 深度参考

Document 模块提供三种 Pro 级装配原语:页面范围拆分、多文档合并,以及 PDF Portfolio(Collection)字典构建。PdfSplitter 会将页面范围提取为独立且结构合规的 PDF,并把整份文档合并为一个重新编号的文件。PdfPortfolio 会构建 Collection 字典,以可排序的 schema 列呈现嵌入文件。每个入口点都会针对恶意输入对输入大小与对象数量设限。

此能力随 NextPDF Pronextpdf/pro)一同发布,并在 Pro 级授权信封激活时启用。缺少该授权的部署不会加载此能力的类。比较各版本并获取授权

本模块的全部类型都位于 NextPDF\Pro\Document 命名空间。PageRangeMergeResult 是来自 NextPDF\Document 的 Core 值对象。

符号参数默认行为返回抛出或失败于说明
PdfSplitter::split()string $pdfData, list<PageRange> $ranges, int $maxBytes = 100_000_000, int $maxRanges = 1000为每个范围构建一个独立的 PDF 分段SplitResult缺少 %PDF 头部时抛出 InvalidArgumentException;触及大小、范围数量或闭包守护时抛出 OverflowException守护在任何解析之前运行
PdfSplitter::splitEvery()string $pdfData, int $pagesPerSegment推导出连续的 N 页范围;最后一段可能更短SplitResult$pagesPerSegment < 1 或缺少头部时抛出 InvalidArgumentException以默认上限委托给 split()
PdfSplitter::extractPages()string $pdfData, PageRange $range将单个范围作为独立 PDF 字节返回string缺少头部时抛出 InvalidArgumentException;触及闭包守护时抛出 OverflowException此路径没有上限参数
PdfSplitter::mergeDocuments()list<string> $pdfs, int $maxInputs = 100, int $maxBytesEach = 100_000_000按顺序把输入合并为一个重新编号的 PDFMergeResult列表为空或输入非 PDF 时抛出 InvalidArgumentException;触及数量、单个输入大小或闭包守护时抛出 OverflowException自 3.1.0 起;最高输入版本决定输出头部
SplitResultreadonly $segments, $ranges, $totalPages携带原始分段字节及源元数据final readonly 值对象
SplitResult::count()统计已生成的分段数int
SplitResult::segment()int $index返回单个分段的字节string索引越界时抛出 OutOfRangeException从零开始索引
PdfPortfolio::__construct()string $viewMode = 'tile'在构造时校验视图模式模式非 tiledetailhidden 时抛出 InvalidArgumentException
PdfPortfolio::addSchema()PortfolioField $field追加一个 schema 列self流式
PdfPortfolio::addEntry()PortfolioEntry $entry追加一个文件条目self流式
PdfPortfolio::getSchema()返回累积的 schema 字段list<PortfolioField>
PdfPortfolio::getEntries()返回累积的文件条目list<PortfolioEntry>
PdfPortfolio::count()统计文件条目int
PdfPortfolio::generateCollectionDictionary()发出 Collection 字典字符串string仅在存在字段时才出现 schema 与 sort 块
PortfolioEntry$filename, $data, $description = '', $mimeType = 'application/octet-stream', $customFields = []不可变的文件条目值对象size() 返回数据的字节长度
PortfolioField$name, PortfolioFieldType $type, $displayName = '', $order = 0, $visible = true不可变的 schema 列值对象effectiveDisplayName() 会回退到 $name
PortfolioFieldType字符串枚举:Text, Date, Number, FileName, Description, Size, ModDate, CreationDate通过 pdfSubtype() 把每个 case 映射到一个 PDF /SubtypestringS, D, N, F, Desc日期类 case 共用子类型 D;数值类 case 共用 N

入口点签名:

public function split(string $pdfData, array $ranges, int $maxBytes = 100_000_000, int $maxRanges = 1000): SplitResult
public function mergeDocuments(
array $pdfs,
int $maxInputs = 100,
int $maxBytesEach = 100_000_000,
): MergeResult
public function __construct(
private readonly string $viewMode = 'tile',
)
public function generateCollectionDictionary(): string

拆分与合并共用同一条对象图流水线:

  • 输入必须以 %PDF 头部开头。大小与数量守护在解析之前运行,触及即抛出 OverflowException
  • 叶子页面通过扫描页面对象标记来检测;页面树节点不计入页数。
  • 解析器以流感知的终止符扫描对每个未压缩的间接对象建立索引。对象 id 的首次出现胜出,因此不会应用增量更新的覆盖。
  • 可继承的页面树属性(/Resources/MediaBox/CropBox/Rotate)会沿其 /Parent 链行走并实体化到每个被提取的页面上,从而使分段自成一体。
  • 每个页面的传递性间接引用闭包会被收集(排除 /Parent 反向边),并重新编号到一个全新的连续 id 空间中。
  • 序列化器会依次发出头部、Catalog、Pages 树、页面对象与闭包对象,接着是带有字节精确偏移的交叉引用表,以及一个指向 xref 关键字的 startxref
  • mergeDocuments 会对每个输入在一个共享 id 空间中重复该流水线。最高的输入 PDF 版本决定输出头部。它是被禁用的 Core 合并器的合规替代,而后者保持 fail-closed。
  • 输出是确定性的。不会发出任何时间戳或随机标识符,因此相同的输入会产生相同的字节。

Portfolio 装配:

  • 构造函数会校验视图模式。发出的 /View 令牌对 tile、detail、hidden 分别为 /T/D/H
  • generateCollectionDictionary() 会发出 /Type /Collection/View 令牌、在存在字段时发出 /Schema 块,以及一个按第一个 schema 字段升序的 /Sort 指令。
  • 每个 schema 字段会发出 /Subtype(来自 pdfSubtype())、/N(转义后的显示名)、/O(顺序)与 /V(可见性)。
  • 字段名会被净化为合法的 PDF 名称令牌;非单词字符会变为下划线。字符串值会被转义为 PDF 字面字符串。
  • 文件条目通过 getEntries() 暴露,供写入层进行嵌入。Collection 字典本身仅携带视图、schema 与 sort。
  • 匹配不到任何页面的范围会产生一个最小化的单页分段(612 x 792 MediaBox),而不是一个错误。
  • 没有可检测页面标记的文档会被计为一页。
  • 存储在对象流内部的页面不会被检测;只有未压缩的间接对象参与提取。
  • 当存在重复对象 id 时,会使用偏移最低的修订版;较晚的增量更新修订版会被忽略。
  • 每个分段的引用闭包上限为 50,000 个对象;恶意的自引用或扇出图会抛出 OverflowException
  • 默认上限:输入 100 MB、1,000 个范围、100 个合并输入。三者均可按调用逐次调整。
  • splitEvery() 会以 InvalidArgumentException 拒绝小于 1 的分段大小。
  • SplitResult::segment() 会以 OutOfRangeException 拒绝越界索引。
  • 两个仅在标点上不同的 schema 字段名会净化为相同的字典键;在发出的 schema 中,较晚的字段会静默覆盖较早的字段。
  • 本模块不执行任何密码学操作;FIPS 模式不会改变其行为。

分段与合并输出遵循 ISO 32000-2 的页面对象模型;源码标注了相关条款。可外部核验的主张:

  • 尾部布局、startxref 字节偏移及 %%EOF 终止符遵循 ISO 32000-2:2020, §7.5.5 —— 参见 ef0f2a4b563b84f81b3e6428612bc47c510d94fc8096849d339abf0f3247d845
  • Collection 字典的 /View 值(/T/D/H)遵循 ISO 32000-2:2020, §12.3.5 —— 参见 5cefaaeb40f3ff98e3aba135ac57c9424a05c43144c1b9b5156bfd4295e08ddd
  • Collection 字段的 /Subtype/N/O/V 条目遵循 ISO 32000-2:2020, §12.3.5(collection field dictionary)—— 参见 6300fbfdc8a913a8dc6f6ae34eff99f2bd03c4313a77777cdd5a8dd856d9537a

这些陈述描述的是经由本模块测试验证的已实现能力。对某个构造的支持并非一致性主张,而一致性也不等于认证;NextPDF 未就本模块持有任何第三方认证。

  • 本模块的全部类均为 final;结果类型与值对象类型为 readonly。拆分器与 Portfolio 类型可追溯至 1.9.0;mergeDocuments() 于 3.1.0 加入。
  • PageRangeMergeResult 是 Core 类型,因此调用点保持跨版本可移植。
  • 分段尾部仅携带 /Size/Root;不会发出任何 /ID 文件标识符或 /Info 字典。
  • 对于增量更新或签名工作流,请将分段字节交给 Writer 模块处理,而不要就地对其进行后期编辑。
  • 本模块不记录任何文档内容。

本页仅记录可外部观察的行为与受支持的公共 API 接口面。内部命名空间路径、辅助类、机制表、运行手册文件名与工单前缀均不在范围之内。