Pular para o conteúdo
getnextpdf.com

Pro edição

Diff

NextPDF\Pro\Diff compara dois documentos PDF e relata o que mudou. O caminho rápido produz um diff de texto alinhado por página; o caminho estruturado adiciona detecção de alterações de imagem e metadados e formata o resultado como JSON ou HTML.

Este recurso vem no NextPDF Pro (nextpdf/pro) e é ativado com um envelope de licença de nível Pro. Uma implantação sem esse direito de uso não carrega as classes do recurso. Compare edições e obtenha uma licença.

Nenhum sinalizador de capacidade em tempo de execução restringe as classes do Diff; elas estão presentes sempre que o pacote Pro está instalado.

Terminal window
composer require nextpdf/pro:^3

PdfDiffer::compare() extrai o texto por página de cada documento, divide-o em linhas e executa um diff de linhas de Myers por par de páginas, produzindo regiões adicionadas, removidas e modificadas. A extração de texto analisa os operadores de exibição de texto da ISO 32000-2:2020 §9.4 (Tj, TJ, ').

StructuredDiffer se baseia nisso: ele agrupa regiões de texto em alterações no nível de parágrafo, compara imagens incorporadas, compara metadados e produz um StructuredDiffResult com um resumo agregado. DiffFormatter serializa esse resultado em uma string JSON ou em um fragmento de relatório HTML.

Quando o leitor de PDF opcional do Artisan está instalado, a extração de texto o utiliza para conteúdo preciso por página; caso contrário, um fallback limitado em nível de byte varre os streams de conteúdo diretamente.

O diferenciador compara texto e estrutura extraídos, não pixels renderizados. Uma comparação estrutural é determinística, barata e mapeia para as alterações editoriais que um revisor considera importantes. Um diff de pixels, em vez disso, sinalizaria ruído de antialiasing e font-hinting como conteúdo. Como um PDF armazena glifos e posicionamento, e não caracteres prontos para leitura, cada comparação primeiro reconstrói o texto a partir do stream de conteúdo. Essa etapa de extração é o motivo pelo qual o leitor do Artisan aprimora a precisão, pelo qual o fallback limitado de FlateDecode troca cobertura por segurança e pelo qual páginas digitalizadas mal geram diff. O alinhamento de páginas permanece baseado em índice para previsibilidade, então uma página inserida é lida como um deslocamento claro a jusante.

Contexto de design: Por que o texto em um PDF não é realmente texto.

  • Entrada. Bytes brutos do PDF para origem e destino. Um buffer que não comece com %PDF gera InvalidArgumentException.
  • Saída (caminho rápido). DiffResult com as listas de regiões added, removed e modified, mais isIdentical(), hasDifferences(), totalChanges().
  • Saída (caminho estruturado). StructuredDiffResult com diffs de parágrafo, diffs de imagem, alterações de metadados e um DiffSummary.
  • Saída de relatório. DiffFormatter emite uma string JSON ou um fragmento HTML. Ele não produz um PDF visual de redlining lado a lado.
  • Limites de recursos. O tamanho do stream de conteúdo descomprimido é limitado para proteger contra bombas de descompressão; o scanner em nível de byte evita backtracking catastrófico de regex em entradas elaboradas.
  • Determinismo. Para entradas idênticas, as regiões de diff e a saída formatada são estáveis.
TypeKindKey members
NextPDF\Pro\Diff\PdfDifferfinal classstatic compare(string $sourcePdf, string $targetPdf): DiffResult, static compareTexts(array $sourcePages, array $targetPages): DiffResult, static extractText(string $contentStream): string
NextPDF\Pro\Diff\StructuredDifferfinal class__construct(?ImageDiffer $imageDiffer = null, ?MetadataDiffer $metadataDiffer = null), compare(string $sourcePdf, string $targetPdf): StructuredDiffResult
NextPDF\Pro\Diff\DiffFormatterfinal classtoJson(StructuredDiffResult $result): string, toHtml(StructuredDiffResult $result): string
NextPDF\Pro\Diff\DiffResultfinal readonly classarray $added, array $removed, array $modified, isIdentical(): bool, hasDifferences(): bool, totalChanges(): int
NextPDF\Pro\Diff\StructuredDiffResultfinal readonly classtext diff, paragraphs, images, metadata changes, summary
NextPDF\Pro\Diff\DiffTypeenumAdded, Removed, Modified, Unchanged
<?php
declare(strict_types=1);
use NextPDF\Pro\Diff\PdfDiffer;
$diff = PdfDiffer::compare(
file_get_contents('v1.pdf'),
file_get_contents('v2.pdf'),
);
if ($diff->hasDifferences()) {
echo $diff->totalChanges(), " text changes detected\n";
}
<?php
declare(strict_types=1);
use NextPDF\Pro\Diff\DiffFormatter;
use NextPDF\Pro\Diff\StructuredDiffer;
function reviewReport(string $oldPdf, string $newPdf): string
{
$result = (new StructuredDiffer())->compare($oldPdf, $newPdf);
// JSON for machine consumption; toHtml() for a review UI fragment.
return (new DiffFormatter())->toJson($result);
}
  • O diff é alinhado por índice de página. Inserir uma página no início desloca todas as páginas posteriores e relata grandes alterações subsequentes — isso é esperado para uma comparação alinhada por índice.
  • A comparação de imagens detecta imagens incorporadas adicionadas, removidas e modificadas; ela não é um diff visual perceptual e não renderiza páginas em pixels.
  • PDFs digitalizados apenas com imagens produzem pouco ou nenhum diff de texto porque nenhum OCR é executado.
  • Sem o leitor opcional do Artisan, a extração usa o fallback limitado; documentos muito comprimidos podem gerar cobertura de texto reduzida.

A extração de texto é linear nos bytes do documento; o diff de Myers é quase linear para documentos semelhantes e quadrático no pior caso por par de páginas. O limite de descompressão limita a memória. Consulte performance_budget.

O fallback em nível de byte usa varredura baseada em strpos em vez de regex ilimitada para evitar backtracking catastrófico em PDFs elaborados, e limita a saída de descompressão. O diff não executa scripts incorporados. Consulte o modelo de segurança do Core.

ClaimSpec clauseStatus
Operador de texto Tj analisado para extraçãoISO 32000-2:2020 §9.4Verificado (conjunto de testes unitários)
Operador de texto em array TJ analisado para extraçãoISO 32000-2:2020 §9.4Verificado (conjunto de testes unitários)
Saída de PDF visual de redlining lado a ladoNão suportado (apenas JSON/HTML)

Não existe equivalente no Core para comparação de documentos. O leitor opcional do Artisan melhora a precisão da extração quando instalado, mas não é obrigatório.

Este é um detector de alterações de conteúdo. Ele não é um analisador forense de diferenças e não produz relatórios probatórios ou de atribuição de adulteração; essas preocupações estão fora do escopo deste módulo.

Esta página documenta apenas o comportamento observável externamente e a superfície pública de API suportada. Caminhos de namespace internos, classes auxiliares, tabelas de mecanismos, nomes de arquivos de runbook e prefixos de tickets estão fora do escopo.