
Das Zusammenstellen einer ansprechenden PDF aus verstreuten Quelldateien ist eine Routineaufgabe, die jedoch fummelig sein kann: Ein Deckblatt muss am Anfang eines Projektberichts stehen, Preisseiten gehören in den zugehörigen Vertrag, und eine Quartalszusammenfassung fügt Diagramme aus einem Dutzend Berichte zusammen. Das manuell zu erledigen bedeutet, mehrere PDF-Reader jonglieren zu müssen und zu hoffen, dass die Seitenreihenfolge stimmt, wobei unterschiedliche Seitengrößen das Problem zusätzlich verschärfen.
Spire.PDF for JavaScript verlagert den gesamten Vorgang in den Browser. Angetrieben von WebAssembly lädt, bearbeitet und speichert es PDF-Dokumente vollständig clientseitig über ein virtuelles Dateisystem (VFS), sodass niemals eine Datei auf einen Backend-Server hochgeladen wird. Dieser Artikel stellt vier unterschiedliche Techniken zum Kopieren von PDF-Seiten zwischen Dokumenten vor – drei, die ganze Seiten verschieben, und eine, die Seiteninhalte als wiederverwendbare Vorlage extrahiert – jeweils mit vollständigen React-Codebeispielen.
Informationen zur Projekteinrichtung und Installation finden Sie unter Integrieren von Spire.PDF for JavaScript in ein React-Projekt. Die folgenden Beispiele setzen voraus, dass Spire.PDF installiert und das WebAssembly-Modul initialisiert wurde.
Vier Möglichkeiten zum Kopieren von PDF-Seiten im Überblick
Bevor wir die einzelnen Methoden untersuchen, bietet die folgende Tabelle einen schnellen Vergleich. Die ersten drei Techniken verschieben unversehrte Seiten und übernehmen automatisch die Abmessungen, Drehung und Ränder der Quellseite. Die vierte entkoppelt den Inhalt von der Seitengeometrie und gibt Ihnen die volle Kontrolle über Zielseitengröße und Zeichenposition.
| Methode | API-Aufruf | Was kopiert wird | Seitengröße | Typischer Anwendungsfall |
|---|---|---|---|---|
| Eine einzelne Seite einfügen | InsertPage |
Eine Seite an einer von Ihnen gewählten Position | Übernimmt von der Quelle | Hinzufügen einer Deck- oder Titelseite am Anfang |
| Einen Seitenbereich einfügen | InsertPageRange |
Einen zusammenhängenden Block von Seiten | Übernimmt von der Quelle | Anhängen eines bestimmten Abschnitts wie Preistabellen |
| Ein ganzes Dokument anhängen | AppendPage |
Jede Seite des Quelldokuments | Übernimmt von der Quelle | Vollständige Dokumente von Ende zu Ende verketten |
| Seiteninhalt als Vorlage zeichnen |
CreateTemplate + DrawTemplate
|
Nur Seiteninhalt, auf eine beliebige Seite gezeichnet | Sie bestimmen die Zielgröße | Inhalte auf verschiedenen Seitengrößen wiederverwenden oder mehrfach wiederholen |
Die ersten drei Methoden sind unkomplizierte Seitenverschiebungen – Quelle auswählen, Ziel auswählen, und die Bibliothek erledigt den Rest. Der Vorlagenansatz ist fortgeschrittener und eröffnet Möglichkeiten, die einfaches Seitenkopieren nicht abdeckt, etwa das Skalieren von Inhalten auf eine andere Seitengröße oder das Aufstempeln derselben Inhalte auf mehrere Seiten. Wir behandeln zuerst die drei Seitenverschiebungsmethoden und untersuchen anschließend die Vorlagentechnik eingehend.
Eine einzelne Seite an eine bestimmte Position kopieren
Die präziseste der vier Methoden, PdfDocument.InsertPage, kopiert eine Seite aus einem Quelldokument und platziert sie an einem exakten Index im Ziel. Der Parameter resultPageIndex steuert, wo die Kopie landet: Übergeben Sie 0, um sie voranzustellen, übergeben Sie die aktuelle Seitenzahl des Ziels, um sie anzuhängen, oder geben Sie einen beliebigen Index dazwischen an, um an dieser Position einzufügen. Wenn Sie resultPageIndex ganz weglassen, wird die Seite standardmäßig am Ende eingefügt.
function App() {
const copyPageAtPosition = async () => {
// Get the Spire.PDF WASM module
const pdfModule = window.wasmModule?.spirepdf;
// Check whether the module is ready
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// Load both the source and the target document into the VFS
const sourceFileName = 'SourceDocument.pdf';
const targetFileName = 'TargetDocument.pdf';
await window.spire.FetchFileToVFS(sourceFileName, "", `${process.env.PUBLIC_URL}/data/`);
await window.spire.FetchFileToVFS(targetFileName, "", `${process.env.PUBLIC_URL}/data/`);
// Load the two documents
const sourceDoc = new pdfModule.PdfDocument();
sourceDoc.LoadFromFile(sourceFileName);
const targetDoc = new pdfModule.PdfDocument();
targetDoc.LoadFromFile(targetFileName);
// Copy page 1 of the source document to the front of the target document
// pageIndex comes from the source document, resultPageIndex is where the copy lands
targetDoc.InsertPage({ ldDoc: sourceDoc, pageIndex: 0, resultPageIndex: 0 });
// Save the result document
const outputFileName = 'CopyPageAtPosition.pdf';
targetDoc.SaveToFile(outputFileName);
sourceDoc.Close();
targetDoc.Close();
// Read the generated file from the VFS and trigger the download
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Copy Page at Position</h1>
<button onClick={copyPageAtPosition}>
Start
</button>
</div>
);
}
export default App;
Von allen vier Kopiermethoden ist
resultPageIndexder einzige Parameter, mit dem Sie die Einfügeposition wählen können. Wenn Sie ihn auf 0 setzen, wird die Seite an erster Stelle platziert, bei 1 an zweiter Stelle, und wenn Sie die aktuelle Seitenzahl des Zieldokuments übergeben, hat das denselben Effekt wie Anhängen.
Das Zieldokument wächst von zwei auf drei Seiten, wobei die erste Seite des Quelldokuments nun die führende Position einnimmt:

Einen Seitenbereich an das Ende kopieren
Wenn Sie mehr als eine Seite, aber weniger als ein ganzes Dokument benötigen, kopiert PdfDocument.InsertPageRange einen zusammenhängenden Block von Seiten, der durch einen Start- und Endindex definiert ist. Anders als InsertPage akzeptiert diese Methode positionale Argumente statt eines Optionsobjekts, und sie hängt die kopierten Seiten immer an das Ende des Ziels an – es gibt keinen Parameter zur Wahl der Einfügeposition. Der Endindex ist inklusive, daher kopiert die Übergabe von (sourceDoc, 1, 2) die Seiten 2 und 3 (nullbasiert).
function App() {
const appendPageRange = async () => {
// Get the Spire.PDF WASM module
const pdfModule = window.wasmModule?.spirepdf;
// Check whether the module is ready
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// Load both the source and the target document into the VFS
const sourceFileName = 'SourceDocument.pdf';
const targetFileName = 'TargetDocument.pdf';
await window.spire.FetchFileToVFS(sourceFileName, "", `${process.env.PUBLIC_URL}/data/`);
await window.spire.FetchFileToVFS(targetFileName, "", `${process.env.PUBLIC_URL}/data/`);
// Load the two documents
const sourceDoc = new pdfModule.PdfDocument();
sourceDoc.LoadFromFile(sourceFileName);
const targetDoc = new pdfModule.PdfDocument();
targetDoc.LoadFromFile(targetFileName);
// Append pages 2 to 3 of the source document to the end of the target document
// Note: these are positional arguments, not an object; endIndex is inclusive
targetDoc.InsertPageRange(sourceDoc, 1, 2);
// Save the result document
const outputFileName = 'CopyPageRange.pdf';
targetDoc.SaveToFile(outputFileName);
sourceDoc.Close();
targetDoc.Close();
// Read the generated file from the VFS and trigger the download
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Copy Page Range</h1>
<button onClick={appendPageRange}>
Copy pages 2-3
</button>
</div>
);
}
export default App;
Das Zieldokument erhält zwei zusätzliche Seiten und wächst damit von zwei auf vier Seiten:

Ein gesamtes Dokument anhängen
Für den einfachsten Fall – jede Seite eines Dokuments in ein anderes zu verschieben – macht PdfDocument.AppendPage die Berechnung von Indizes vollständig überflüssig. Übergeben Sie das Quelldokumentobjekt, und alle seine Seiten werden in ihrer ursprünglichen Reihenfolge an das Ziel angehängt. Um mehrere Dokumente zu verketten, rufen Sie AppendPage nacheinander mit jedem Quelldokument auf.
function App() {
const appendWholeDocument = async () => {
// Get the Spire.PDF WASM module
const pdfModule = window.wasmModule?.spirepdf;
// Check whether the module is ready
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// Load both the source and the target document into the VFS
const sourceFileName = 'SourceDocument.pdf';
const targetFileName = 'TargetDocument.pdf';
await window.spire.FetchFileToVFS(sourceFileName, "", `${process.env.PUBLIC_URL}/data/`);
await window.spire.FetchFileToVFS(targetFileName, "", `${process.env.PUBLIC_URL}/data/`);
// Load the two documents
const sourceDoc = new pdfModule.PdfDocument();
sourceDoc.LoadFromFile(sourceFileName);
const targetDoc = new pdfModule.PdfDocument();
targetDoc.LoadFromFile(targetFileName);
// Use AppendPage when the whole document has to be copied; all pages are appended in order
targetDoc.AppendPage({ doc: sourceDoc });
// Save the result document
const outputFileName = 'CopyAllPages.pdf';
targetDoc.SaveToFile(outputFileName);
sourceDoc.Close();
targetDoc.Close();
// Read the generated file from the VFS and trigger the download
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Copy Whole Document</h1>
<button onClick={appendWholeDocument}>
Start
</button>
</div>
);
}
export default App;
Alle vier Seiten des Quelldokuments werden an das Ziel angehängt, wodurch es von zwei auf sechs Seiten erweitert wird:

Seiteninhalt mit einer Vorlage kopieren
Die drei oben genannten Methoden behandeln eine Seite als unteilbare Einheit: Sie wird mit beibehaltener Größe, Drehung und Rändern verschoben. Doch die Dokumentzusammenstellung in der Praxis erfordert oft eine feinere Steuerung – das Platzieren des Inhalts einer Seite auf einer anders großen Seite, das Vergrößern oder Verkleinern oder das Aufstempeln desselben Inhalts auf mehrere Seiten. Hier kommt PdfPageBase.CreateTemplate ins Spiel.
CreateTemplate extrahiert den visuellen Inhalt einer Seite in ein PdfTemplate-Objekt. Anschließend zeichnen Sie diese Vorlage mit Canvas.DrawTemplate auf eine beliebige Seite und geben Position und Größe des Zeichenbereichs an. Die Vorlage ist von der Geometrie der Originalseite entkoppelt, sodass Sie sie in jedem Maßstab, an jeder Position und auf jeder Seitengröße rendern können – und Sie können dieselbe Vorlage so oft zeichnen, wie Sie möchten.
Dies macht Vorlagen besonders nützlich für Szenarien wie:
- Den Inhalt eines A5-Covers ohne weißen Rand zentriert auf einer A4-Seite platzieren
- Ein Wasserzeichen oder Hintergrundmuster aus einer vorhandenen Seite erstellen
- Ein Formularlayout in verschiedenen Maßstäben auf mehrere neue Seiten duplizieren
function App() {
const copyPageWithTemplate = async () => {
// Get the Spire.PDF WASM module
const pdfModule = window.wasmModule?.spirepdf;
// Check whether the module is ready
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// Load the PDF file to work on into the VFS
const inputFileName = 'SourceDocument.pdf';
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);
// Load the document
const doc = new pdfModule.PdfDocument();
doc.LoadFromFile(inputFileName);
// Take the page to be reused and turn it into a template: read the content once, draw it many times
const sourcePage = doc.Pages.get_Item(0);
const template = sourcePage.CreateTemplate();
// First placement: insert an A4 page at position 2, a different size from the source,
// and draw the content scaled to 297.6 x 421.6 at (80, 80)
const page1 = doc.Pages.Insert(1, new pdfModule.SizeF(595.0, 842.0), new pdfModule.PdfMargins({ margin: 0.0 }));
page1.Canvas.DrawTemplate(template, new pdfModule.PointF(80.0, 80.0), new pdfModule.SizeF(297.6, 421.6));
// Second placement: insert another A4 page, drawing the same template smaller in the lower right
const page2 = doc.Pages.Insert(2, new pdfModule.SizeF(595.0, 842.0), new pdfModule.PdfMargins({ margin: 0.0 }));
page2.Canvas.DrawTemplate(template, new pdfModule.PointF(320.0, 460.0), new pdfModule.SizeF(200.0, 283.3));
// Save the result document
const outputFileName = 'CopyPageWithTemplate.pdf';
doc.SaveToFile(outputFileName);
doc.Close();
// Read the generated file from the VFS and trigger the download
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Copy Page with Template</h1>
<button onClick={copyPageWithTemplate}>
Start
</button>
</div>
);
}
export default App;
Einige Details, die bei DrawTemplate beachtenswert sind:
- Größenargument: Wenn das dritte Argument (Zielgröße) weggelassen wird, wird die Vorlage in ihren ursprünglichen Abmessungen ohne Skalierung gerendert. Auf einer größeren Zielseite nimmt der Inhalt nur einen Teil des verfügbaren Platzes ein.
-
Seitenerstellung: Die Abmessungen und Ränder der Zielseite stammen von
Pages.Insert, nicht von der Vorlage. Im Beispiel sorgen Nullränder an allen Seiten dafür, dass der Zeichenursprung mit der oberen linken Ecke der Seite zusammenfällt. -
Mehrfaches Zeichnen: Dasselbe
template-Objekt wird zweimal auf zwei separate Seiten an unterschiedlichen Positionen und in unterschiedlichen Maßstäben gezeichnet, was die Wiederverwendbarkeit demonstriert.
Der Inhalt von Seite 1 erscheint nun auf zwei neu eingefügten A4-Seiten in unterschiedlichen Maßstäben und Positionen, wodurch das Dokument von vier auf sechs Seiten wächst:

Häufig gestellte Fragen
Das Erstellen einer Seite mit new PdfMargins(0.0) löst Arg_NullReferenceException aus
Ursache: Der PdfMargins-Konstruktor interpretiert ein bloßes numerisches Argument als internes Handle und nicht als Randwert. Der Aufruf new pdfModule.PdfMargins(0.0) erzeugt daher ein Objekt, das keine gültigen Ränder darstellt – der Zugriff auf seine Eigenschaft Left oder Top löst Arg_NullReferenceException aus, und die Übergabe an die Seitenerstellung liefert unerwartete Ergebnisse.
Lösung: Übergeben Sie Ränder immer als Konfigurationsobjekt. Für einheitliche Nullränder verwenden Sie { margin: 0.0 }; für einzelne Seitenwerte geben Sie jede Seite explizit an:
// Zero margins on all four sides
const margins = new pdfModule.PdfMargins({ margin: 0.0 });
// Or set each side separately
const custom = new pdfModule.PdfMargins({ left: 20.0, top: 20.0, right: 20.0, bottom: 20.0 });
Beim Kopieren von Seiten wird ein Fehler wegen außerhalb des Bereichs liegendem oder umgekehrtem Bereich ausgelöst
Ursache: Seitenindizes sind nullbasiert, und endIndex in InsertPageRange ist inklusive. Der gültige Bereich reicht daher von 0 bis Pages.Count - 1. Die Angabe eines Index außerhalb dieses Bereichs löst Index out of range aus, während das Setzen von startIndex auf einen höheren Wert als endIndex The start index is greater then the end index. auslöst.
Lösung: Sichern Sie die Obergrenze ab, indem Sie sie vor dem Aufruf der Methode auf Pages.Count begrenzen:
// To copy pages 2 to 4: start = 1, end = 3, with the page count as the upper bound
const start = 1;
const end = Math.min(3, sourceDoc.Pages.Count - 1);
targetDoc.InsertPageRange(sourceDoc, start, end);
Eine gedrehte Seite hat nach dem Kopieren die falsche Ausrichtung
Ursache: CreateTemplate() erfasst den gezeichneten Inhalt der Seite, aber nicht ihren Drehwinkel (den Eintrag /Rotate). Wenn die Quellseite eine Drehung aufweist, ist das Koordinatensystem der Vorlage gegenüber der Zielseite fehlausgerichtet – wird sie direkt gezeichnet, landet der Inhalt außerhalb des sichtbaren Bereichs, und die resultierende Kopie hat eine Rotation von 0.
Lösung: Bevorzugen Sie bei gedrehten Quellseiten eine Ganzseitenkopie, damit der Drehwinkel mit dem Inhalt übertragen wird:
// Whole-page copy: the rotation angle comes with the page
targetDoc.InsertPage({ ldDoc: sourceDoc, pageIndex: 0, resultPageIndex: 1 });
Wenn der Vorlagenansatz unvermeidbar ist, setzen Sie die Drehung der Quellseite vorübergehend zurück, bevor Sie die Vorlage extrahieren, und stellen Sie dann den ursprünglichen Winkel sowohl auf der Quell- als auch auf der neuen Seite wieder her:
const rotation = sourcePage.Rotation.value;
// Zero it temporarily so the template exports at the page's real coordinates
sourcePage.Rotation = 0;
const newPage = doc.Pages.Insert(1, sourcePage.Size, new pdfModule.PdfMargins({ margin: 0.0 }));
newPage.Canvas.DrawTemplate(sourcePage.CreateTemplate(), new pdfModule.PointF(0.0, 0.0));
// Restore the source page and give the copy the same angle
sourcePage.Rotation = rotation;
newPage.Rotation = rotation;
Um das Evaluierungswasserzeichen aus Ausgabedokumenten zu entfernen oder den vollen Funktionsumfang freizuschalten, kontaktieren Sie den Vertrieb für eine temporäre 30-Tage-Lizenz.