跳转到内容
getnextpdf.com

Pro 版本

Converter

NextPDF\Pro\Converter 读取一份现有 PDF,并将其内容导出为三种基于文本的目标格式之一:带定位的 HTML、简化的 SVG,或纯文本。它是一个内容提取导出器,而不是像素级精确的 PDF 渲染器。

此功能随 NextPDF Pronextpdf/pro)发布,并通过 Pro 层级的授权信封激活。没有该权限的部署不会加载此功能的类。比较各版本并获取授权

没有任何运行时能力标志对该模块进行门控。只要安装并自动加载了 Pro 包,Converter 类即可解析。

Terminal window
composer require nextpdf/pro:^3

Converter 解析 PDF 内容流内的文本显示运算符 —— 按 ISO 32000-2:2020 §9.4 的 TjTJ' —— 并为每一页重建一个近似表示。它从 TdTm 文本运算符读取定位,从 Tf 读取字号,然后将点(point)映射到输出坐标。

对外暴露了三个转换器,每种 ConversionTarget 一个:

  • PdfToHtmlConverter 将每一页包裹在一个带定位的容器中,并为每段文本运行(text run)发出绝对定位的 <div> 元素。输出是一份自包含的 HTML5 文档。
  • PdfToSvgConverter 解析一组有限的绘图运算符(经由 re 的矩形、经由 m/l 的线段)以及文本,并为单页发出相应的 <rect><line><text> 元素。
  • PdfToTextConverter 仅逐页提取解码后的文本,各页之间以分页标记分隔。

这是一个刻意设限的导出器。它近似文本位置;它不进行回流,不进行栅格化,也不还原矢量路径、底纹、裁剪、透明度或嵌入图像。若要在相反方向上进行全保真的 HTML 到 PDF 渲染,请使用 Core HTML 管线。

PDF 将文本存储为带定位的字形显示运算符,而非语义字符,因此没有可靠的文档文本可供读回。为此,Converter 直接扫描内容流运算符 —— TjTJ',以及用于放置的 TdTmTf —— 并重建一个近似布局,而不是对页面进行回流或栅格化。正是这种有界扫描,使得导出在字节长度上保持线性、对相同输入具有确定性,并且在不执行嵌入逻辑的情况下对不受信任的字节保持安全。它也划定了诚实的上限:字形不会被反向映射到 Unicode,因此使用自定义编码的字体会以原始字节形式导出,精确的视觉保真不在范围内。 设计背景:为什么 PDF 中的文本其实并不是文本

  • 输入。 原始 PDF 字节(string)。空字符串会抛出 InvalidArgumentException
  • 输出。 一个 ConversionResult 值对象,持有所产出的字符串、ConversionTarget、已处理的页数,以及一次处理耗时测量。
  • 覆盖范围。 文本导出(Tj/TJ/')是经过验证的路径,由单元测试套件演练。SVG 导出仅覆盖矩形、直线和文本。RGB 描边颜色尚未传播到 SVG 输出。
  • 确定性。 对于相同的输入和配置,所产出的 HTML、SVG 或文本字节流是稳定的。processingTimeMs 字段是一次墙钟测量,不属于确定性接口的一部分。
  • 编码。 HTML 输出经过 htmlspecialchars 转义;SVG 输出经过 XML 转义。常见的 PDF 字符串转义序列(\n\r\t\(\)\\)会针对文本目标进行解码。
类型种类关键成员
NextPDF\Pro\Converter\PdfToHtmlConverterfinal classconvert(string $pdfData, ?ConversionConfig $config = null): ConversionResult
NextPDF\Pro\Converter\PdfToSvgConverterfinal classconvert(string $pdfData, int $pageIndex = 0, ?ConversionConfig $config = null): ConversionResult
NextPDF\Pro\Converter\PdfToTextConverterfinal classconvert(string $pdfData): ConversionResult, extractPage(string $pdfData, int $pageIndex): string
NextPDF\Pro\Converter\ConversionConfigfinal readonly class__construct(ConversionTarget $target, bool $embedFonts = false, bool $embedImages = true, float $scaleFactor = 1.0, string $cssClass = 'pdf-page')
NextPDF\Pro\Converter\ConversionResultfinal readonly classstring $output, ConversionTarget $target, int $pageCount, float $processingTimeMs, size(): int, isValid(): bool
NextPDF\Pro\Converter\ConversionTargetenumHtml5, Svg, PlainText; mimeType(): string, fileExtension(): string
<?php
declare(strict_types=1);
use NextPDF\Pro\Converter\PdfToTextConverter;
$pdf = file_get_contents('report.pdf');
$result = (new PdfToTextConverter())->convert($pdf);
echo $result->pageCount, " pages, ", $result->size(), " bytes of text\n";
echo $result->output;
<?php
declare(strict_types=1);
use NextPDF\Pro\Converter\ConversionConfig;
use NextPDF\Pro\Converter\ConversionTarget;
use NextPDF\Pro\Converter\PdfToHtmlConverter;
function exportPreview(string $pdfBytes): string
{
if ($pdfBytes === '') {
throw new InvalidArgumentException('empty PDF payload');
}
$config = new ConversionConfig(
target: ConversionTarget::Html5,
scaleFactor: 1.0,
cssClass: 'doc-preview',
);
$result = (new PdfToHtmlConverter())->convert($pdfBytes, $config);
if (! $result->isValid()) {
throw new RuntimeException('converter produced no output');
}
return $result->output;
}
  • 一份没有 BT/ET 文本块的 PDF 会产出空输出,或只有页面外壳的输出;扫描件(仅含图像)PDF 不会产出任何文本,因为没有 OCR 步骤。
  • PdfToSvgConverter 一次只转换单页,由 $pageIndex 选定;越界的索引会产出空的页面流。
  • 定位是近似的。以非文本变换放置的文本、旋转文本或分栏流式文本,可能无法重现其原始视觉布局。
  • 不会应用字形到 Unicode 的映射;来自使用自定义编码的字体的文本,可能会以原始字节序列的形式导出。

解析随 PDF 字节长度呈线性。内存随输入加上所产出的输出字符串而变化。performance_budget front-matter 是一份典型办公文档每次调用的参考值。

转换器以有界的 strpos/substr 扫描来解析不受信任的 PDF 字节、遍历文本运算符;它不执行嵌入的 JavaScript,也不跟随外部引用。请将导出的 HTML 视为不受信任的内容,并针对其目的地进行适当转义。参见 Core 安全模型。

主张规范条款状态
解析 Tj 文本显示运算符ISO 32000-2:2020 §9.4已验证(单元测试套件)
解析 TJ 数组文本显示运算符ISO 32000-2:2020 §9.4已验证(单元测试套件)
完整矢量/栅格页面保真不支持(不在范围内)

PDF 导出没有 Core 等价物。对于正向(从 HTML 创作 PDF),开源 Core HTML 管线是受支持的路径。参见 /modules/core/html/

Converter 是一个 Pro 层级的文本/形状导出器。它不执行 OCR、语义重建或文档理解。这些是单独的事项,且不由本模块提供。

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