Zum Inhalt springen
getnextpdf.com

Pro Edition

Webview

Webview liefert ein linearisiertes (Fast Web View) PDF über HTTP aus, sodass ein Client das Rendern von Seite 1 aus einem kleinen führenden Präfix beginnen kann, während der Rest der Datei noch im Transfer ist. Es umhüllt die rohen Bytes als ein LinearizedDocument, beantwortet Range-Anfragen mit RFC-9110-Partial-Content-Antworten über einen PSR-7-ByteRangeResponder und kann (über FirstPageProber) beweisen, dass die erste Seite im Präfix in sich abgeschlossen ist.

Diese Funktion ist in NextPDF Pro (nextpdf/pro) enthalten und wird mit einem Lizenz-Envelope der Pro-Stufe aktiviert. Ein Deployment ohne diese Berechtigung lädt die Klassen der Funktion nicht. Editionen vergleichen und Lizenz erwerben.

Es gibt kein separates per-Feature-Lizenz-Flag. Der Responder wird zur Laufzeit an Ihre eigenen PSR-17-Factories angebunden — ein ResponseFactoryInterface und ein StreamFactoryInterface — und der Media-Type ist standardmäßig application/pdf als Konstruktorargument, kein Lizenzschalter.

Terminal-Fenster
composer require nextpdf/pro

Der Code liegt unter dem Namespace NextPDF\Pro\Webview.

Ein linearisiertes PDF ist so angeordnet, dass die erste Seite des Dokuments — das Linearisierungs-Parameter-Dictionary, der primäre Hint-Stream und die Objekte von Seite 1 — in einem führenden Abschnitt liegt, der am /E-Offset endet. Webview verwandelt dieses Layout in eine progressive Auslieferung.

LinearizedDocument::fromBytes() parst die Bytes über die Lese-seitige LinearizationView von Core (Pro implementiert das Parsen der Linearisierung niemals neu) und weist alles zurück, was kein verwendbares linearisiertes Dokument ist: gar nicht linearisiert, eine deklarierte /L-Länge, die nicht der tatsächlichen Byte-Länge entspricht, oder ein /E-End-of-First-Page-Offset, der kein positiver Offset innerhalb der Datei ist. Die Konstruktion ist daher total — sobald Sie ein LinearizedDocument halten, ist jeder Offset, den es offenlegt, vertrauenswürdig.

ByteRangeResponder beantwortet anschließend eine HTTP-Anfrage. Er ist ausschließlich gegen PSR-7 / PSR-17 implementiert, ohne Framework-Kopplung. Er kündigt stets Accept-Ranges: bytes und einen starken, deterministischen SHA-256-ETag an, parst den Range-Header des Clients gemäß RFC 9110 §14 und gibt entweder ein vollständiges 200 OK, einen 206 Partial Content Single Range, eine 206-multipart/byteranges-Antwort für mehrere Ranges oder ein 416 Range Not Satisfiable zurück.

FirstPageProber ist die Seite des strukturellen Nachweises: Er quantifiziert das First-Page-Präfix, den Anteil der gesamten Datei, den dieses Präfix darstellt, und ob der primäre Hint-Stream vollständig darin liegt — die Eigenschaft, die es einem Reader erlaubt, die Objekte von Seite 1 allein aus dem Präfix zu lokalisieren.

Webview parst die Linearisierung niemals selbst neu. Es leiht sich die Lese-seitige LinearizationView von Core, sodass die Auslieferungsschicht einen einzigen auditierten Parser erbt statt einer zweiten, driftenden Kopie. Die Konstruktion ist bewusst total. LinearizedDocument::fromBytes() weist ein fehlerhaftes Layout vorab zurück, sodass jeder Offset, dem eine Range-Antwort vertraut, zuerst validiert wurde. Der Responder spricht ausschließlich PSR-7 und PSR-17, sodass derselbe Code ein linearisiertes PDF aus jedem HTTP-Stack ausliefert. Genau diese Disziplin macht die progressive Range-Auslieferung sicher genug, um sie in großem Umfang nicht vertrauenswürdigen Clients auszusetzen.

Design-Hintergrund: Hochvolumige Dokumentenerzeugung.

Wie das progressive Byte-Range-Serving funktioniert

Abschnitt betitelt „Wie das progressive Byte-Range-Serving funktioniert“
  1. Bauen Sie ein LinearizedDocument aus den gerenderten PDF-Bytes. Ungültige Eingaben lösen vorab eine UnsupportedDocumentException aus.
  2. Übergeben Sie das Dokument und das eingehende PSR-7-ServerRequestInterface an ByteRangeResponder::respond(). Der Responder liest Range (und die optionale If-Range-Precondition) und erzeugt das korrekte PSR-7-ResponseInterface.
  3. Der Client fordert zuerst das führende Präfix an (oder Sie pushen es mit firstPageResponse()), rendert Seite 1 und fordert dann die übrigen Ranges an, während der Benutzer scrollt.

Das Byte-Range-Modell verwendet inklusive Offsets gemäß RFC 9110 §14.1.2: Ein ByteRange ist firstBytelastByte über eine Repräsentation von contentLength, und sein Content-Range-Feld ist bytes first-last/length.

  • LinearizedDocument::fromBytes() ist total: Ein nicht-linearisiertes Dokument, eine /L-Abweichung oder ein nicht-positiver / außerhalb der Datei liegender /E-Offset lösen jeweils eine UnsupportedDocumentException aus, statt ein unsicheres Dokument zu erzeugen.
  • Der ETag ist ein starker SHA-256-Entity-Tag über die exakten Bytes, einmalig bei der Konstruktion memoisiert. Identische Render-Eingaben ergeben identische Bytes und daher einen identischen ETag, sodass Caches und If-Range sich vorhersehbar verhalten.
  • Eine Anfrage ohne anwendbares Range gibt 200 OK mit dem vollständigen Body zurück. Ein If-Range, das nicht zum aktuellen starken ETag passt, bewirkt, dass das Range ignoriert und ein vollständiges 200 zurückgegeben wird (RFC 9110 §13.1.5). Nur die starke Entity-Tag-Form von If-Range wird honoriert; ein HTTP-Date-If-Range wird als Nicht-Treffer behandelt.
  • Eine nicht erkannte Range-Unit oder ein syntaktisch ungültiges Range wird ignoriert, und ein vollständiges 200 wird zurückgegeben (RFC 9110 §14.2).
  • Ein erfüllbares Range gibt 206 Partial Content mit Content-Range zurück; mehrere erfüllbare Ranges geben 206 multipart/byteranges zurück. Gültige Byte-Ranges, von denen keines erfüllbar ist, geben 416 mit Content-Range: bytes */length zurück (RFC 9110 §15.3.7).
  • firstPageResponse() emittiert ein 206, das genau das Byte-Range der ersten Seite [0, /E - 1] trägt — die Server-Push-Form von „erste Seite vor dem vollständigen Download“.

Das Folgende spiegelt die dokumentierte öffentliche API wider. Das Repository liefert für dieses Modul kein lauffähiges Beispiel aus.

use NextPDF\Pro\Webview\LinearizedDocument;
use NextPDF\Pro\Webview\ByteRangeResponder;
$document = LinearizedDocument::fromBytes($pdfBytes);
$responder = new ByteRangeResponder($responseFactory, $streamFactory);
$response = $responder->respond($document, $request);
use NextPDF\Pro\Webview\LinearizedDocument;
use NextPDF\Pro\Webview\ByteRangeResponder;
use NextPDF\Pro\Webview\FirstPageProber;
use NextPDF\Pro\Webview\Exception\UnsupportedDocumentException;
try {
$document = LinearizedDocument::fromBytes($pdfBytes);
} catch (UnsupportedDocumentException $e) {
// Not a usable linearized document — fall back to plain full delivery.
// ...
return;
}
$prober = new FirstPageProber($document);
if ($prober->isFirstPageSelfContained()) {
// Push exactly the first page's bytes for an instant render.
$response = (new ByteRangeResponder($responseFactory, $streamFactory))
->firstPageResponse($document);
}
  • Webview erfordert ein echt linearisiertes PDF. Wenn das gerenderte Dokument nicht linearisiert ist, aktivieren Sie die Linearisierung zur Render-Zeit oder liefern Sie es mit einer einfachen vollständigen Auslieferung aus — respondToBytes() kann weiterhin Ranges über beliebige (nicht-linearisierte) Bytes ausliefern, wenn Sie nur Range-Unterstützung benötigen, keine First-Page-Semantik.
  • Inkrementelle Updates sind relevant: Ein Dokument, das über seine deklarierte /L hinaus angehängt wurde, wird als Längenabweichung zurückgewiesen, weil Byte-Range-Offsets dann nicht mehr vertrauenswürdig wären.
  • Der Responder deckelt die Anzahl der distinkten Ranges, die er pro Anfrage honoriert. Eine Anfrage, die mehr zusammengeführte Ranges als die Obergrenze oder mehr Gesamt-Bytes als die gesamte Repräsentation verlangt, lässt ihr Range ignorieren und wird mit einem vollständigen 200 bedient.

Das First-Page-Präfix ist der /E-End-of-First-Page-Offset, auf die Dateilänge geklemmt, sodass FirstPageProber::prefixFraction() meldet, wie klein der initiale Abruf relativ zur gesamten Datei ist — für ein mehrseitiges Dokument ist genau das der Sinn von Fast Web View. Der Antwortaufbau schneidet aus dem In-Memory-Byte-String; die Kosten sind proportional zu den ausgewählten Bytes. Der ETag wird einmal pro Dokument berechnet. Messen Sie mit repräsentativen Dokumenten.

Behandeln Sie die Eingabe als nicht vertrauenswürdig. LinearizedDocument::fromBytes() validiert die Linearisierungs-Invarianten, bevor irgendein Offset verwendet wird. Der Responder weist einen contentType mit Steuerzeichen zurück, um Header-Injection zu verhindern, leitet eine Multipart-Boundary ab, die garantiert nicht innerhalb des Bodys auftritt, und führt überlappende Ranges zusammen und begrenzt deren Anzahl und Gesamtgröße, um sich gegen die Multipart-Range-Amplification-Klasse von Denial-of-Service zu verteidigen (Apache HTTPD CVE-2011-3192). Dieses Modul protokolliert keinen Dokumentinhalt.

Die Byte-Range-Auslieferung folgt RFC 9110 (HTTP Semantics) — §14 für Range-Anfragen, §13.1.5 für If-Range und §15.3.7 für 416. Das Linearisiertes-Dokument-Modell ist das in ISO 32000-2 Annex F beschriebene Fast-Web-View-Layout. Das Modul behauptet keine weiteren externen Klausel-Identifikatoren über das durch seine Tests verifizierte Verhalten hinaus.

Enterprise ändert das Verhalten von Webview nicht. Enterprise ergänzt höherstufige Compliance- und Archivierungsfunktionen, die separat dokumentiert sind; sie sind nicht erforderlich, um ein linearisiertes PDF über Byte-Ranges auszuliefern.

Diese Seite dokumentiert ausschließlich extern beobachtbares Verhalten und die unterstützte öffentliche API-Oberfläche. Interne Namespace-Pfade, Hilfsklassen, Mechanismus-Tabellen, Runbook-Dateinamen und Ticket-Präfixe liegen außerhalb des Geltungsbereichs.