Zum Inhalt springen

Schnellstart — erstes Edge-Rendering

Diese Seite zeigt, wie Sie einen HTML-String in eine PDF-Datei umwandeln. Jeder gezeigte Aufruf ist einer Methode zugeordnet; das Verhalten jeder Methode wird in tests/Unit/Cloudflare/CloudflareHtmlRendererTest.php verifiziert.

  • Ein Worker-Endpunkt, der den Render-Vertrag über HTTPS bereitstellt.
  • Ein Bearer-Token, das der Worker akzeptiert.
  • Ein PSR-18-Client und PSR-17-Factorys, die im Pfad verfügbar sind (siehe /integrations/cloudflare/install/).

Der aus CloudflareResponseParser abgeleitete Worker-Vertrag lautet: Bei Erfolg gibt er HTTP 200 zurück. Die Antwort enthält entweder Content-Type: application/pdf (rohe PDF-Bytes) oder Content-Type: application/json mit einem base64-codierten pdf-Feld. Ein Status ungleich 200 oder ein Body, der nicht mit der %PDF-Markierung beginnt, gilt als Fehlschlag.

<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Cloudflare\CloudflareRendererConfig;
$config = new CloudflareRendererConfig(
workerUrl: 'https://pdf-renderer.example.workers.dev/render',
apiToken: getenv('CF_PDF_TOKEN') ?: throw new RuntimeException('CF_PDF_TOKEN not set'),
);

Das Token wird aus der Umgebung gelesen und niemals fest im Code hinterlegt. workerUrl muss HTTPS verwenden. Wenn Sie eine http://-URL übergeben, weist die Bridge sie mit Worker URL must use HTTPS zurück, bevor eine Anfrage gesendet wird.

use GuzzleHttp\Client;
use GuzzleHttp\Psr7\HttpFactory;
use NextPDF\Cloudflare\CloudflareHtmlRenderer;
$httpFactory = new HttpFactory();
$renderer = new CloudflareHtmlRenderer(
config: $config,
httpClient: new Client(), // PSR-18 ClientInterface
requestFactory: $httpFactory, // PSR-17 RequestFactoryInterface
streamFactory: $httpFactory, // PSR-17 StreamFactoryInterface
logger: null, // optional PSR-3 LoggerInterface
responseFactory: $httpFactory, // PSR-17; enables the pinned transport
);

Der Konstruktor erfordert vier Argumente: die Konfiguration, den PSR-18-Client, die Request-Factory und die Stream-Factory. Vier weitere Argumente sind optional: der Logger, die Local-Renderer-Factory, eine explizite HTML-Sicherheitsrichtlinie und die Response-Factory. Wenn Sie die Response-Factory bereitstellen, wird der gepinnte cURL-Transport aktiviert, sofern ein aufgelöster IP-Satz oder ein SPKI-Pin-Satz vorhanden ist (siehe /integrations/cloudflare/security-and-operations/).

use NextPDF\Cloudflare\Exception\CloudflareNotAvailableException;
use NextPDF\Cloudflare\Exception\CloudflareRenderException;
try {
$result = $renderer->render('<h1>Hello from the edge</h1>');
if (!$result->isValid()) {
throw new RuntimeException('Worker did not return a valid PDF');
}
file_put_contents('output.pdf', $result->pdfData);
printf("Wrote %d bytes from edge %s in %.1f ms\n",
$result->size(),
$result->renderLocation !== '' ? $result->renderLocation : 'unknown',
$result->renderTimeMs,
);
} catch (CloudflareRenderException $e) {
// Worker answered but the render failed (HTTP error or malformed body).
fwrite(STDERR, 'Render failed: ' . $e->getMessage() . PHP_EOL);
exit(1);
} catch (CloudflareNotAvailableException $e) {
// Worker unreachable and no usable fallback.
fwrite(STDERR, 'Edge unavailable: ' . $e->getMessage() . PHP_EOL);
exit(2);
}

render() verwendet standardmäßig die A4-Breite (595.28 PDF-Punkte) und eine automatisch erkannte Höhe (heightPt: 0). Die beiden Exception-Typen sind bewusst voneinander getrennt. CloudflareRenderException steht für einen Worker-seitigen Fehlschlag und wird nicht mit einem Fallback wiederholt. CloudflareNotAvailableException bedeutet, dass die Edge nicht erreicht werden konnte und kein lokaler Fallback verfügbar war.

CloudflareRenderResult ist final readonly. Die folgenden Felder werden im Binärpfad aus den Response-Headern und im JSON-Pfad aus den JSON-Feldern gesetzt.

MemberQuelle
pdfDataRohe PDF-Bytes
widthPtDie von Ihnen angeforderte Breite
heightPtX-Pdf-Height-Pt-Header / JSON heightPt; verwendet standardmäßig 841.89 (A4-Höhe), falls nicht vorhanden oder nicht positiv
contentHeightPxX-Content-Height-Px / JSON contentHeightPx
renderLocationAus dem Suffix des CF-Ray-Headers (Binärpfad) oder JSON renderLocation abgeleitet
renderTimeMsX-Render-Time-Ms / JSON renderTimeMs
size()strlen($pdfData)
isValid()true, wenn die Bytes mit %PDF beginnen

Optional — Benutzerdefinierte Papiergröße, Schriftarten, CSS

Abschnitt betitelt „Optional — Benutzerdefinierte Papiergröße, Schriftarten, CSS“
$result = $renderer->render(
html: '<div style="font-family: NotoSansCJK;">繁體中文文件</div>',
widthPt: 595.28,
heightPt: 841.89, // explicit A4; 0 lets the Worker auto-detect
fontFiles: ['NotoSansCJKtc-Regular.ttf'],
);

fontFiles ist nur dann von Bedeutung, wenn in der Konfiguration r2FontBucket gesetzt ist. Die Nutzlast enthält dann den Bucket-Namen und die angeforderten Schriftdateipfade, damit der Worker sie laden kann.

if ($renderer->isAvailable()) {
$result = $renderer->render($html);
}

isAvailable() sendet eine authentifizierte HTTP-HEAD-Anfrage an die Worker-URL. Die Methode gibt true zurück, wenn der Status unter 500 liegt. Sie gibt false zurück, ohne eine Ausnahme zu werfen, wenn die Konfiguration ungültig ist oder die Anfrage fehlschlägt. Betrachten Sie das Ergebnis als Hinweis, nicht als Garantie. Der Worker kann den anschließenden POST trotzdem fehlschlagen lassen.

  • /integrations/cloudflare/production-usage/ — Fallback-Anbindung, Telemetrie, R2-Archivierung.
  • /integrations/cloudflare/troubleshooting/ — jeder Fehlschlag ist seiner Exception und Meldung zugeordnet.
  • /integrations/cloudflare/configuration/ — die vollständige Feldreferenz.