
Sie erstellen eine Dokumentliste für einen Kunden, und der Kunde fragt: "Kann ich die Seiten sehen, bevor ich sie herunterlade?" Und schon besitzen Sie eine Rendering-Funktion, die Sie nicht geplant hatten. Dieselbe Anfrage taucht überall auf – ein Thumbnail-Streifen unter einem Posteingang, eine Vorschaukarte, die in einen Chat eingefügt wird, eine Folie, die aus einem Deck gezogen und in sozialen Netzwerken gepostet wird. In jedem Fall kann ein PDF nicht inline angezeigt werden, aber ein Bild seiner Seiten schon.
Sobald diese Umstellung erfolgt ist, entscheiden vier Faktoren darüber, ob die Arbeit brauchbar ist: welche Seiten, welches Format, wie scharf und wie die Dateien zum Nutzer gelangen. Die meisten PDF-zu-Bild-Beispiele beantworten nur den ersten Punkt und überlassen es Ihnen, den Rest in der Produktion zu entdecken.
Spire.PDF for JavaScript rendert Seiten im Browser über WebAssembly und liefert Ihnen jede Seite als Bildstream. Alle vier dieser Entscheidungen treffen Sie selbst, und jede davon ist ein einzelnes Argument oder eine geänderte Dateiendung. Dateien werden über ein virtuelles Dateisystem (VFS) ein- und ausgegeben, sodass nichts irgendwohin hochgeladen wird.
In diesem Artikel erfahren Sie, wie Sie:
- jede Seite eines PDFs als PNG rendern und das Set als ZIP herunterladen
- die Konvertierung auf eine einzelne Seite oder einen Seitenbereich beschränken
- je nach Verwendungszweck des Bildes zwischen PNG, JPEG und BMP wechseln
- mithilfe von DPI Schärfe gegen Dateigröße abwägen
- das Ergebnis als Download, als einzelne Dateien oder direkt in Ihre React-UI liefern
- verstümmelten oder leeren Text aufgrund fehlender Schriftarten beheben
Voraussetzungen
Diese Schritt-für-Schritt-Anleitung setzt ein React-Projekt voraus, in dem Spire.PDF for JavaScript installiert und das WASM-Modul initialisiert ist. Informationen zur Einrichtung finden Sie unter Integrieren von Spire.PDF for JavaScript in ein React-Projekt.
Sie benötigen:
- Ein in das VFS geladenes PDF
- Das WASM-Modul, erreichbar unter
window.wasmModule.spirepdf - Das Paket
jszip, wenn Sie mehrere Seiten in einem Download bündeln möchten (npm install jszip)
Jede Seite in PNG konvertieren
Der Fall über das gesamte Dokument ist der, zu dem Sie am häufigsten greifen werden: PDF öffnen, jede Seite durchlaufen, jede in einen Stream rendern, jeden Stream in einen Ordner im VFS schreiben, diesen Ordner anschließend zippen und ihn dem Browser als Download übergeben.
import JSZip from "jszip";
function App() {
const convertToImage = async () => {
// Get the Spire.PDF WASM module
const pdfModule = window.wasmModule?.spirepdf;
// Check if the WASM module is ready
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// Load the PDF file and fonts into VFS
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'Flowers.pdf';
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);
// Create PdfDocument object and load the PDF document
let doc = new pdfModule.PdfDocument();
doc.LoadFromFile(inputFileName);
// Create an output directory to hold the converted images
let outputDirectoryName = "ImagesFolders/";
window.dotnetRuntime.Module.FS.mkdirTree(outputDirectoryName);
// Loop through each page and save it as an image
for (let i = 0; i < doc.Pages.Count; i++) {
const outputFileName = outputDirectoryName + "ConvertedImages_" + i + ".png";
let stream = doc.SaveAsImage({ pageIndex: i });
stream.Save(outputFileName);
stream.Dispose();
}
doc.Dispose();
// Read the converted files from VFS and trigger download
const zip = new JSZip();
let items = await window.dotnetRuntime.Module.FS.readdir(outputDirectoryName);
items = items.filter((item) => item !== "." && item !== "..");
for (const item of items) {
const itemPath = `${outputDirectoryName}/${item}`;
const fileData = await window.dotnetRuntime.Module.FS.readFile(itemPath);
zip.file(item, fileData);
}
// Convert the ZIP to a Blob and trigger the browser download
const zipBlob = await zip.generateAsync({ type: "blob" });
const url = URL.createObjectURL(zipBlob);
const a = document.createElement('a');
a.href = url;
a.download = 'ImagesFolders';
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Convert PDF To Image</h1>
<button onClick={convertToImage}>
Generate
</button>
</div>
);
}
export default App;
Jede Seite des PDFs wird über SaveAsImage als PNG-Bild exportiert und in eine ZIP-Datei zum Herunterladen gebündelt

Was der Code tut:
-
doc.SaveAsImage({ pageIndex: i })rendert eine Seite und gibt einen Bildstream zurück. Seitenindizes sind nullbasiert,pageIndex: 0ist also die erste Seite. -
stream.Save(outputFileName)schreibt diesen Stream in das VFS. Die hier übergebene Dateiendung legt das Format fest – mehr dazu weiter unten. -
stream.Dispose()gibt den Stream frei, bevor die nächste Seite gerendert wird. Wenn Sie dies bei einem langen Dokument auslassen, wird ohne Nutzen Speicher verschwendet. - Die Abfolge
FS.mkdirTree→FS.readdir→FS.readFileexistiert, weil das WASM-Modul in sein eigenes Dateisystem schreibt und nicht in den Download-Ordner des Browsers. JSZip ist das, was diesen Ordner in etwas verwandelt, das der Nutzer speichern kann. - Das Rendern ist schreibgeschützt. Das Quell-PDF wird geöffnet, gelesen und freigegeben; es wird niemals verändert.
Hinweis: Dies erzeugt ein Bild jeder Seite, was genau das ist, was Sie für Vorschauen, Thumbnails und zum Teilen benötigen. Wenn Sie stattdessen die im PDF eingebetteten Originalbilddateien möchten – das eigentliche Diagramm oder Foto in seiner nativen Auflösung, nicht ein Screenshot der Seite, auf der es sich befindet –, ist das ein anderer Vorgang: siehe Bilder aus einem PDF in JavaScript (React) extrahieren.
Nur bestimmte Seiten konvertieren
Ein 200-seitiges Dokument zu rendern, um drei Thumbnails zu erzeugen, ist verschwendete Arbeit. Da der Seitendurchlauf nur eine for-Schleife über doc.Pages.Count ist, ist die Einschränkung nur eine Frage der Änderung der Grenzen.
Eine einzelne Seite – das Cover oder eine bestimmte Anlage:
// Render only the first page
const outputFileName = outputDirectoryName + "cover.png";
let stream = doc.SaveAsImage({ pageIndex: 0 });
stream.Save(outputFileName);
stream.Dispose();
Ein zusammenhängender Bereich – die Seiten 3 bis 5, unter Verwendung der nullbasierten Indizes 2 bis 4:
const startPage = 2;
const endPage = 4;
for (let i = startPage; i <= endPage && i < doc.Pages.Count; i++) {
let stream = doc.SaveAsImage({ pageIndex: i });
stream.Save(outputDirectoryName + "page_" + (i + 1) + ".png");
stream.Dispose();
}
Eine handverlesene Auswahl – Seiten, die nicht nebeneinander liegen:
const pagesToRender = [0, 7, 12];
for (const pageIndex of pagesToRender) {
if (pageIndex >= doc.Pages.Count) continue;
let stream = doc.SaveAsImage({ pageIndex });
stream.Save(outputDirectoryName + "page_" + (pageIndex + 1) + ".png");
stream.Dispose();
}
Die Prüfung i < doc.Pages.Count ist wichtig, wenn die Seitenliste aus einer Benutzereingabe statt aus einer fest codierten Konstante stammt – ein Index außerhalb des gültigen Bereichs ist ein Laufzeitfehler, den Sie lieber nicht ausliefern möchten.
Beachten Sie das (i + 1) in den Dateinamen. Nullbasierte Indizes sind für die API richtig und für Menschen falsch; wenn Sie Dateien nach der Seitenzahl benennen, die der Nutzer sieht, vermeiden Sie später eine ganze Klasse von Support-Tickets.
Empfohlener Artikel: Wenn Sie die ursprünglichen Bild-Objekte aus dem PDF benötigen statt einer gerenderten Seite – das eingebettete Diagramm oder Foto in seiner nativen Auflösung –, siehe Bilder aus einem PDF in JavaScript (React) extrahieren.
Ein Ausgabeformat wählen
Das Format wird vollständig durch die Dateiendung bestimmt, die Sie an stream.Save übergeben. Nichts anderes in der Pipeline ändert sich.
stream.Save(outputDirectoryName + "page_1.png"); // PNG
stream.Save(outputDirectoryName + "page_1.jpg"); // JPEG
stream.Save(outputDirectoryName + "page_1.bmp"); // BMP
| Format | Dateiendung | Was Sie erhalten | Greifen Sie dazu, wenn |
|---|---|---|---|
| PNG | .png |
Verlustfrei. Textkanten und dünne Linien bleiben scharf. Größere Dateien. | Dokumentseiten, UI-Vorschauen, alles mit Text oder Diagrammen |
| JPEG | .jpg |
Verlustbehaftet. Deutlich kleiner. Keine Transparenz, und Kompressionsartefakte zeigen sich um kleine Schrift herum. | Fotografische oder gescannte Seiten, E-Mail-Anhänge, Lieferung mit Größenbeschränkung |
| BMP | .bmp |
Unkomprimiert. Sehr groß. | Legacy-Pipelines, die ausdrücklich unkomprimierte Bitmaps erfordern |
Die praktische Regel: Wenn die Seite überwiegend Text enthält, verwenden Sie PNG. Die Kompression von JPEG ist auf fotografische Inhalte abgestimmt und erzeugt auf einer textlastigen Seite sichtbare Verwischungen an den Zeichenrändern, die keine Qualitätseinstellung vollständig beseitigt. Handelt es sich bei der Seite um ein gescanntes Foto, reduziert JPEG die Dateigröße erheblich mit geringem sichtbaren Verlust.
Die Auflösung (DPI) festlegen
SaveAsImage rendert standardmäßig mit 96 DPI, was einem typischen Bildschirm entspricht. Das ist die richtige Einstellung für Thumbnails und Bildschirmvorschauen. Sie reicht nicht aus, wenn jemand hineinzoomt, die Seite druckt oder das Bild einer OCR zuführt.
Übergeben Sie dpiX und dpiY, um dies zu ändern:
// Export each page as an image at 150 DPI
for (let i = 0; i < doc.Pages.Count; i++) {
let stream = doc.SaveAsImage({ pageIndex: i, dpiX: 150, dpiY: 150 });
stream.Save(outputDirectoryName + "highres_" + i + ".png");
stream.Dispose();
}
Auflösung ist kein kostenloses Upgrade – die Pixelanzahl skaliert mit dem Quadrat der DPI, sodass die Kosten schnell steigen:
| DPI | Relative Pixelanzahl im Vergleich zu 96 DPI | Vergleichbar mit | Angemessen für |
|---|---|---|---|
| 96 (Standard) | 1× | Standardbildschirm | Thumbnails, Inline-Vorschauen, Galerie-Leisten |
| 150 | ~2,4× | Retina-Display, leichtes Zoomen | E-Mail-Anhänge, Vorschauen, in die Nutzer hineinzoomen könnten, Probedrucke |
| 300 | ~9,8× | Druckqualität | Druckausgabe, OCR-Eingabe, Archiv-Master |
Zwei Dinge folgen aus dieser Tabelle. Erstens: Der Sprung von 96 auf 300 vervielfacht den Aufwand und den Speicherbedarf um etwa das Zehnfache, greifen Sie also bei einem 200-seitigen Dokument nicht zu 300, es sei denn, jemand wird es tatsächlich drucken. Zweitens: dpiX und dpiY sind aus gutem Grund separate Argumente – normalerweise werden sie auf denselben Wert gesetzt, und unterschiedliche Werte verzerren die Seite.
Die Bilder paketieren oder als Vorschau anzeigen
Das Rendern der Seiten ist die eine Hälfte der Arbeit; die andere Hälfte besteht darin, sie zum Nutzer zu bringen. Drei Muster decken fast alles ab.
Alles in eine ZIP-Datei bündeln – der Ansatz aus dem ersten Beispiel. Am besten geeignet, wenn der Nutzer einen Ordner mit Dateien möchte, und die einzige Option, die auf Dutzende Seiten skaliert, ohne den Browser mit Download-Aufforderungen zu bombardieren.
Ein einzelnes Bild direkt herunterladen – kein JSZip nötig, wenn es nur eine Datei gibt:
const outputFileName = 'cover.png';
let stream = doc.SaveAsImage({ pageIndex: 0 });
stream.Save(outputFileName);
stream.Dispose();
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'image/png' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
Die Bilder in Ihrer React-UI behalten – überhaupt kein Download. Dies ist die richtige Wahl für Vorschaubereiche und Thumbnail-Leisten, wo die Bilder temporär sind und ein Download-Ordner voller page_1.png-Dateien nur Ballast wäre:
const renderPreviewStrip = async () => {
const pdfModule = window.wasmModule?.spirepdf;
if (!pdfModule) return;
await window.spire.FetchFileToVFS('Flowers.pdf', "", `${process.env.PUBLIC_URL}/data/`);
let doc = new pdfModule.PdfDocument();
doc.LoadFromFile('Flowers.pdf');
const previewUrls = [];
for (let i = 0; i < doc.Pages.Count; i++) {
const tempName = `preview_${i}.png`;
let stream = doc.SaveAsImage({ pageIndex: i, dpiX: 72, dpiY: 72 });
stream.Save(tempName);
stream.Dispose();
const fileArray = window.dotnetRuntime.Module.FS.readFile(tempName);
const blob = new Blob([fileArray], { type: 'image/png' });
previewUrls.push(URL.createObjectURL(blob));
}
doc.Dispose();
// previewUrls can now be rendered as <img src={url} /> in a thumbnail strip
return previewUrls;
};
Beachten Sie dpiX: 72 im Vorschaufall: Thumbnails benötigen keine vollständige Auflösung, und wenn Sie sie kleiner rendern, bleibt die Leiste reaktionsschnell. Denken Sie daran, URL.revokeObjectURL(url) für jede URL aufzurufen, wenn die Komponente unmountet wird, sonst verlieren Sie bei jedem erneuten Rendern Speicher.
Das könnte Sie auch interessieren: Sie arbeiten mit einer Reihe von Bildern statt mit einem PDF – Sie möchten Scans oder Fotos zu einem einzigen Dokument zusammenfügen? Das ist Bilder in JavaScript (React) in PDF konvertieren.
Verstümmelten Text beheben: Schriftarten laden
Ein PDF bettet die verwendeten Schriftarten normalerweise ein, aber nicht immer – und wenn nicht, muss der Renderer etwas ersetzen. Im Browser gibt es keine Betriebssystem-Schriftartenbibliothek, auf die zurückgegriffen werden kann, sodass eine fehlende Schriftart zu Leerraum oder Kästchen wird.
Die Lösung besteht darin, die Schriftdatei dort abzulegen, wo die WASM-Laufzeit sie erwartet, bevor Sie rendern:
// Load a TrueType font into the VFS font directory before converting
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
ARIALUNI.TTF ist es wert, gekannt zu werden: Es deckt gängige CJK-Zeichen ebenso ab wie lateinische Zeichen, was es zur sichereren Standardwahl macht, wenn Ihre Nutzer Dokumente in Sprachen hochladen, die Sie nicht aufgezählt haben. Wenn Sie ausschließlich englische Dokumente verarbeiten, hält eine kleinere Schriftart den Download leichter.
Da dies ausgeführt wird, bevor eine Seite gerendert wird, genügt eine Prüfung auf fehlende Schriftarten am Anfang Ihrer Konvertierungsfunktion – Sie müssen die Schriftarten nicht pro Seite neu laden.
FAQ
Verändert die Konvertierung eines PDFs in Bilder das ursprüngliche PDF?
Nein. SaveAsImage rendert Seiten und gibt neue Bilddaten zurück; das Quelldokument wird schreibgeschützt geöffnet und anschließend freigegeben. Ihr ursprüngliches PDF bleibt unberührt.
Wie konvertiere ich nur die erste Seite?
Rufen Sie SaveAsImage einmal mit pageIndex: 0 auf, statt eine Schleife zu verwenden. Siehe Nur bestimmte Seiten konvertieren.
Warum ist meine Ausgabe größer als das ursprüngliche PDF?
Weil eine gerenderte Seite Pixel speichert, während ein PDF Zeichenanweisungen speichert. Eine textlastige PDF-Seite umfasst oft nur wenige Kilobyte; ein PNG derselben Seite mit 300 DPI kann Megabyte groß sein. Reduzieren Sie auf 96–150 DPI oder wechseln Sie zu JPEG, wenn die Größe wichtiger ist als die Wiedergabetreue.
Kann ich die Bilder in meiner App anzeigen, anstatt sie herunterzuladen?
Ja – erstellen Sie Objekt-URLs aus den Bilddaten und verwenden Sie sie als <img>-Quellen. Siehe Die Bilder paketieren oder als Vorschau anzeigen. Denken Sie nur daran, die URLs freizugeben, wenn Sie fertig sind.
Verursacht ein sehr langes Dokument Probleme?
Seiten werden innerhalb der Schleife eine nach der anderen gerendert, sodass das WASM-Modul ungefähr jeweils ein Seitenbild hält statt des gesamten Dokuments. Bei extrem langen Dateien konvertieren Sie in Blöcken und hängen Sie sie nach und nach an das Archiv an, anstatt jedes Bild in einem Array zu halten.
Was ist der Unterschied zwischen dem Konvertieren einer Seite in ein Bild und dem Extrahieren von Bildern aus einem PDF?
Beim Konvertieren wird die gesamte Seite – Text, Layout, Bilder, Hintergründe – als ein flaches Bild gerendert. Beim Extrahieren werden die im Dokument eingebetteten ursprünglichen Bildobjekte in ihrer nativen Auflösung herausgezogen. Verwenden Sie die Konvertierung für Vorschauen und zum Teilen; verwenden Sie die Extraktion, wenn Sie die ursprüngliche Grafik selbst benötigen.
Wohin gelangen die konvertierten Dateien eigentlich?
In das virtuelle Dateisystem von WASM, nicht auf Ihren Server und nicht auf die Festplatte des Nutzers. Nichts verlässt den Browser – der einzige Weg, wie Dateien zum Nutzer gelangen, ist der Download- oder Objekt-URL-Schritt, den Sie selbst schreiben.
Siehe auch
Suchen Sie die umgekehrte Richtung – Bilder zurück in ein PDF verwandeln? Das ist Bilder in JavaScript (React) in PDF konvertieren. Der Rest der PDF-Seiten-Pipeline in React: