Pular para o conteúdo
getnextpdf.com

Pro edição

Writer

O módulo Writer acrescenta revisões de atualização incremental a um PDF e empacota objetos pequenos em Object Streams. O writer incremental impõe uma regra de somente acréscimo (append-only): os bytes que existiam antes da revisão não devem mudar.

Este recurso é fornecido no NextPDF Pro (nextpdf/pro) e é ativado com um envelope de licença de nível Pro. Uma implantação sem essa habilitação não carrega as classes do recurso. Compare as edições e obtenha uma licença. Não há um sinalizador de licença separado por recurso; o código é fornecido com a edição Pro.

Terminal window
composer require nextpdf/pro:^3

O código reside sob o namespace NextPDF\Pro\Writer.

Duas capacidades são fornecidas:

  • IncrementalUpdateWriter grava uma nova revisão. Ele reescreve o catálogo com entradas mescladas, anexa uma tabela de referência cruzada tradicional para os objetos novos e modificados e grava um trailer que faz o link com a revisão anterior. Ele impõe uma regra de somente acréscimo (append-only) fail-closed.
  • ObjectStreamWriter agrupa objetos pequenos em um único Object Stream compactado. Isso reduz o tamanho da tabela de referência cruzada e melhora a compressão. Ele rejeita objetos que excederiam o tamanho máximo do fluxo e rejeita um fluxo vazio.

A regra de somente acréscimo (append-only) protege as assinaturas existentes. Cada byte que o buffer continha antes da revisão deve aparecer inalterado na mesma posição após a revisão. Se qualquer byte anterior mudar, o writer gera um erro e não produz saída.

A escolha crítica é onde reside o portão de somente acréscimo (append-only). Ele fica no escopo do writer, não apenas em orquestradores de nível superior, para que todo chamador presente e futuro herde a cobertura fail-closed. A verificação é um teste puro de igualdade de prefixo: o writer tira um instantâneo do prefixo do buffer antes de acrescentar e, em seguida, confirma que cada byte anterior permanece inalterado depois. Isso protege qualquer assinatura cujo /ByteRange cobria o prefixo, já que um único byte alterado a invalidaria silenciosamente. Tabelas de referência cruzada tradicionais e um ponteiro /Prev carregam a nova revisão, porque as atualizações incrementais devem acrescentar em vez de reescrever. O custo de verificação é linear em relação ao prefixo existente, e esse custo é aceito deliberadamente: a integridade dos bytes assinados supera uma segunda cópia.

Contexto de design: Atualizações incrementais e por que importam.

  • IncrementalUpdateWriter::writeRevision(...) retorna o offset em bytes da nova tabela de referência cruzada, para que você possa encadear revisões adicionais.
  • O writer verifica que o prefixo original é byte-igual antes e depois da gravação. Uma divergência gera uma exceção de writer que carrega um estado de violação de somente acréscimo (append-only).
  • A nova revisão usa uma tabela de referência cruzada tradicional e um trailer com um ponteiro /Prev; é permitido misturar tabelas e fluxos entre revisões.
  • ObjectStreamWriter::addObject() gera um erro de estouro quando adicionar um objeto excederia o tamanho máximo do fluxo (65.536 bytes descompactados para índice mais corpo).
  • ObjectStreamWriter::build() gera um erro quando nenhum objeto foi adicionado; caso contrário, ele retorna o conteúdo compactado do Object Stream.

O exemplo a seguir reflete a API pública documentada. O repositório não fornece um exemplo executável para este módulo.

use NextPDF\Pro\Writer\ObjectStreamWriter;
$writer = new ObjectStreamWriter();
$writer->addObject(10, $serializedObjectBody);
$objStm = $writer->build();
use NextPDF\Pro\Writer\IncrementalUpdateWriter;
$newXrefOffset = IncrementalUpdateWriter::writeRevision(
$buffer,
$registry,
$prevXrefOffset,
$catalogObject,
$catalogEntries,
$catalogUpdates,
$newObjectNumbers,
$fileId,
);
// A WriterException here means the append-only rule was violated.
// Treat it as a hard failure; do not emit the output.
  • A verificação de somente acréscimo (append-only) copia o prefixo existente. O custo cresce com o tamanho do documento já gravado. Esse custo é intencional e protege os bytes assinados.
  • O limite de tamanho do Object Stream é sobre o índice combinado e o corpo antes da compressão. Agrupe os objetos de acordo.
  • Os Object Streams não devem conter certos tipos de objeto (por exemplo, o dicionário de criptografia). Coloque esses como objetos indiretos diretos.

A verificação de somente acréscimo (append-only) é linear em relação ao tamanho do prefixo do documento existente. O empacotamento em Object Stream reduz o tamanho da referência cruzada e melhora a compressão ao custo de uma passagem de compressão adicional. Não há número de taxa de transferência publicado. Meça com documentos representativos.

O writer incremental é fail-closed. Se um caminho de código fosse mudar um byte que uma assinatura anterior cobria, o writer gera um erro em vez de produzir um documento. Isso protege a integridade da assinatura para fluxos de trabalho encadeados por revisão. Nenhum conteúdo de documento é registrado em log.

A fonte anota a gramática de atualização incremental e o modelo de Object Stream na ISO 32000-2 e os requisitos de encadeamento de revisões no perfil PAdES da ETSI EN 319 142-1. Como o corpus RAG estava indisponível no momento da redação, esta página repete apenas as referências de cláusula que a própria fonte declara e não afirma nenhum identificador de cláusula externo adicional.

O Enterprise acrescenta recursos de ciclo de vida de assinatura de nível superior (validação de longo prazo e renovação) que se baseiam em atualizações incrementais em nível de comportamento. O módulo Writer fornece apenas a primitiva de revisão; esses recursos de nível superior são documentados separadamente e não são necessários para gravar uma revisão.

Sem o Pro, use o writer básico do NextPDF Core; as revisões de atualização incremental com o portão de somente acréscimo (append-only) e o empacotamento em Object Stream são adições do Pro. Consulte /modules/writer/.

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