Ir al contenido

Inspect: introspección y comprobaciones previas de PDF

El módulo Inspect lee un PDF existente e informa de su contenido: una puntuación de complejidad, auditorías de fuentes e imágenes, indicios de conformidad y marcas de riesgo. Una política de comprobaciones previas convierte ese informe en una decisión de pass/fail, para poder filtrar un documento antes de que entre en un flujo.

Estabilidad: experimental. La introspección es una superficie en evolución. La forma de InspectResult, el conjunto de marcas de riesgo y la ruta de inspección acelerada opcional pueden cambiar entre versiones menores. Conviene usarlo para diagnóstico y filtrado; aún no conviene fijar contratos de larga duración sobre la forma del resultado.

Ventana de terminal
composer require nextpdf/core:^3

Inspector es el punto de entrada. Implementa InspectorInterface y expone un único método: inspect(string $pdfData, InspectConfig $config = new InspectConfig()): InspectResult. Es de solo lectura: analiza un PDF y lo caracteriza; no modifica el documento.

InspectResult es el informe estructurado. Reúne la puntuación de complejidad, las auditorías, los indicios y un conjunto de RiskFlag. Permite consultar hasRisks() / hasRisk(RiskFlag $flag), de modo que el código llamador pueda ramificar según un riesgo concreto en lugar de analizar texto libre. ComplexityScore expone una puntuación numérica junto con una banda category(). FontAuditEntry e ImageAuditEntry describen los recursos incrustados. ComplianceHint señala posibles problemas de conformidad. InspectIssue registra un hallazgo concreto. InspectDepth define la profundidad de la inspección, y toSpectrumDepth() la asigna a la ruta acelerada cuando el sidecar Spectrum está disponible. La inspección también se ejecuta sin el sidecar. El sidecar solo cambia el rendimiento, no el contrato. InspectResponseParser construye un InspectResult a partir de una respuesta sin procesar (por ejemplo, la respuesta de la ruta acelerada) con un id de traza opcional.

PreflightPolicy es la capa de decisión. evaluate(InspectResult $result) aplica una política configurada a un resultado y devuelve el desenlace de esa política. Todo el módulo está marcado como @since 2.2.0.

TipoMiembros claveFunción
Inspectorinspect(string $pdfData, InspectConfig $config): InspectResultInspector de PDF de solo lectura (@since 2.2.0)
InspectResulthasRisks(), hasRisk(RiskFlag), métodos de acceso a score/auditInforme de inspección estructurado (@since 2.2.0)
ComplexityScorecategory()Puntuación numérica de complejidad + banda (@since 2.2.0)
FontAuditEntry / ImageAuditEntrymétodos de acceso a recursosAuditorías de recursos incrustados (@since 2.2.0)
ComplianceHint / InspectIssuemétodos de acceso a hallazgosIndicios de conformidad y hallazgos (@since 2.2.0)
InspectDepth (enum)toSpectrumDepth()Profundidad de inspección → ruta acelerada (@since 2.2.0)
PreflightPolicyevaluate(InspectResult): array, toArray()Decisión pass/fail de comprobaciones previas (@since 2.2.0)
InspectResponseParserparse(array, InspectConfig, ?string $traceId): InspectResultConstruye un resultado a partir de una respuesta sin procesar (@since 2.2.0)

Ejecutar composer docs:generate-api-php -- --module=Inspect para obtener la tabla completa de PHPDoc.

Origen: examples/34-inspect-layout-boxes.php muestra cómo leer la geometría de la página. Para inspeccionar el perfil de riesgo de cualquier PDF:

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Inspect\Inspector;
$result = (new Inspector())->inspect(file_get_contents('/srv/in/incoming.pdf'));
if ($result->hasRisks()) {
echo "Complexity: {$result->complexityScore()->category()}; risks present.\n";
}

Filtrar un PDF entrante mediante una política de comprobaciones previas y rechazarlo ante cualquier riesgo.

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Inspect\Inspector;
use NextPDF\Inspect\PreflightPolicy;
use Psr\Log\LoggerInterface;
final readonly class IngestPreflight
{
public function __construct(
private Inspector $inspector,
private PreflightPolicy $policy,
private LoggerInterface $logger,
) {}
public function accept(string $pdfData): bool
{
$result = $this->inspector->inspect($pdfData);
$verdict = $this->policy->evaluate($result);
if ($verdict !== []) {
$this->logger->warning('PDF rejected at preflight.', ['findings' => $verdict]);
return false;
}
return true;
}
}
  • inspect() es de solo lectura. Nunca modifica ni repara la entrada; no hay que esperar que devuelva un documento «corregido».
  • hasRisk(RiskFlag) es la comprobación precisa. Ramificar solo según hasRisks() trata todos los riesgos por igual; normalmente conviene usar una marca concreta.
  • InspectDepth controla el coste. Una inspección profunda de un PDF grande es notablemente más lenta; elija la profundidad más superficial que responda a su pregunta.
  • La ruta acelerada por Spectrum cambia el rendimiento, no el contrato del resultado. Conviene programar contra InspectResult, no contra la forma de la respuesta acelerada.
  • PreflightPolicy::evaluate() devuelve los hallazgos; no lanza excepciones. Un resultado vacío es un pass: la decisión debe basarse en el valor de retorno.

El coste de la inspección crece con el tamaño del documento y la InspectDepth elegida. La inspección superficial es rápida; una auditoría profunda de un PDF grande puede acercarse al presupuesto. La ruta Spectrum descarga el análisis pesado cuando está disponible. El performance_budget de 1500 ms de reloj / 64 MB de pico es la carga de trabajo de referencia. El perfil de reproducibilidad es structural: un resultado puede incluir un id de traza y la medición de tiempos. Dos ejecuciones pueden diferir en esos campos, mientras que los hallazgos son estables para la misma entrada.

Inspector::inspect() analiza bytes de PDF no confiables —ese es todo su propósito—, así que la entrada debe tratarse como hostil. Ejecutar la inspección en un worker restringido para documentos suministrados por el usuario y acotar el tamaño de la entrada aguas arriba. Un PDF deliberadamente complejo es un vector de denegación de servicio independientemente de la profundidad. El resultado describe el documento, pero no lo sanea: un veredicto de «riesgo bajo» es una heurística, no una garantía de seguridad. Las cadenas y los metadatos extraídos deben tratarse como no confiables. Consultar el modelo de amenazas del motor en /modules/core/security/.

Este módulo informa de indicios de conformidad; no emite el veredicto de conformidad autorizado. ComplianceHint señala posibles problemas de forma heurística. El veredicto de conformidad autorizado de PDF/A, PDF/UA e ISO 32000-2 proviene de los validadores de referencia accionados por /modules/core/cli/ y por el oráculo y las suites golden descritas en /modules/core/conformance/. Un resultado limpio de Inspect no debe tratarse como una certificación de conformidad.