Come convertire pagine PDF in immagini in JavaScript (React)

2026-09-11 10:01:49 Allen Yang
AI Summarize:
ChatGPT
ChatGPT ✓
Claude ✓
Grok ✓
Perplexity ✓
Quick
Quick
Concise overview
Highlights
Key takeaways
Detailed
Structured explanation
Brief
One sentence summary
Summarize |

PDF pages rendered as PNG images in a React application using Spire.PDF for JavaScript

Stai sviluppando un elenco di documenti per un cliente e il cliente chiede: "posso vedere le pagine prima di scaricarle?" Così, ti ritrovi con una funzionalità di rendering che non avevi previsto. La stessa richiesta emerge ovunque — una striscia di miniature sotto una casella di posta, una scheda di anteprima incollata in una chat, una diapositiva estratta da una presentazione e pubblicata sui social. In ogni caso un PDF non può essere mostrato inline, ma un'immagine delle sue pagine sì.

Una volta effettuato questo passaggio, quattro decisioni determinano se il lavoro è utilizzabile: quali pagine, quale formato, quanto nitide e come i file raggiungono l'utente. La maggior parte degli esempi di conversione da PDF a immagine risponde solo alla prima domanda e ti lascia scoprire il resto in produzione.

Spire.PDF for JavaScript esegue il rendering delle pagine nel browser tramite WebAssembly e ti restituisce ogni pagina come flusso di immagini. Tutte e quattro queste decisioni spettano a te, e ciascuna richiede un singolo argomento o una semplice modifica dell'estensione del file. I file entrano ed escono attraverso un file system virtuale (VFS), quindi nulla viene caricato da nessuna parte.

In questo articolo imparerai come:

  • Eseguire il rendering di ogni pagina di un PDF in PNG e scaricare il set come ZIP
  • Limitare la conversione a una singola pagina o a un intervallo di pagine
  • Passare tra PNG, JPEG e BMP a seconda dell'uso previsto dell'immagine
  • Bilanciare nitidezza e dimensione del file usando i DPI
  • Consegnare il risultato come download, come file singoli o direttamente nella tua interfaccia React
  • Correggere testo illeggibile o vuoto causato da font mancanti

Prerequisiti

Questa guida presuppone un progetto React con Spire.PDF for JavaScript installato e il modulo WASM inizializzato. Per la configurazione, consulta Integrare Spire.PDF for JavaScript in un progetto React.

Avrai bisogno di:

  • Un PDF caricato nel VFS
  • Il modulo WASM raggiungibile su window.wasmModule.spirepdf
  • Il pacchetto jszip, se vuoi raggruppare più pagine in un unico download (npm install jszip)

Convertire ogni pagina in PNG

Il caso dell'intero documento è quello a cui ricorrerai più spesso: apri il PDF, scorri ogni pagina, esegui il rendering di ciascuna in un flusso, scrivi ogni flusso in una cartella del VFS, quindi comprimi quella cartella in uno ZIP e la passi al browser come download.

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;

Ogni pagina del PDF esportata come immagine PNG tramite SaveAsImage e raggruppata in un file ZIP per il download

Each page of the PDF exported as a PNG image via SaveAsImage and bundled into a ZIP file for download

Cosa fa il codice:

  • doc.SaveAsImage({ pageIndex: i }) esegue il rendering di una pagina e restituisce un flusso di immagini. Gli indici delle pagine partono da zero, quindi pageIndex: 0 è la prima pagina.
  • stream.Save(outputFileName) scrive quel flusso nel VFS. L'estensione che passi qui determina il formato — ne parleremo più avanti.
  • stream.Dispose() rilascia il flusso prima che venga eseguito il rendering della pagina successiva. Ometterlo su un documento lungo spreca memoria senza alcun beneficio.
  • La sequenza FS.mkdirTree → FS.readdir → FS.readFile esiste perché il modulo WASM scrive nel proprio file system, non nella cartella di download del browser. JSZip è ciò che trasforma quella cartella in qualcosa che l'utente può salvare.
  • Il rendering è di sola lettura. Il PDF di origine viene aperto, letto e rilasciato; non viene mai modificato.

Nota: Questo produce un'immagine di ogni pagina, che è ciò che serve per anteprime, miniature e condivisione. Se invece vuoi i file immagine originali incorporati nel PDF — il grafico o la foto reale alla loro risoluzione nativa, non uno screenshot della pagina che li contiene — si tratta di un'operazione diversa: consulta Estrarre immagini da un PDF in JavaScript (React).


Convertire solo pagine specifiche

Eseguire il rendering di un documento di 200 pagine per produrre tre miniature è lavoro sprecato. Poiché la scansione delle pagine è solo un ciclo for su doc.Pages.Count, restringerlo è questione di modificare i limiti.

Una singola pagina — la copertina o un allegato specifico:

// Render only the first page
const outputFileName = outputDirectoryName + "cover.png";
let stream = doc.SaveAsImage({ pageIndex: 0 });
stream.Save(outputFileName);
stream.Dispose();

Un intervallo contiguo — dalle pagine 3 alla 5, usando gli indici zero-based da 2 a 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();
}

Un insieme scelto a mano — pagine che non sono consecutive:

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();
}

Il controllo i < doc.Pages.Count è importante quando l'elenco delle pagine proviene dall'input dell'utente anziché da una costante codificata — un indice fuori intervallo è un errore di runtime che preferiresti non distribuire.

Nota il (i + 1) nei nomi dei file. Gli indici zero-based sono corretti per l'API e sbagliati per gli esseri umani; denominare i file in base al numero di pagina che l'utente vede evita in futuro una serie di richieste di supporto.

Articolo consigliato: quando hai bisogno degli oggetti immagine originali contenuti nel PDF anziché di una pagina renderizzata — il grafico o la foto incorporati alla loro risoluzione nativa — consulta Estrarre immagini da un PDF in JavaScript (React).


Scegliere un formato di output

Il formato è determinato interamente dall'estensione che passi a stream.Save. Nient'altro nella pipeline cambia.

stream.Save(outputDirectoryName + "page_1.png");  // PNG
stream.Save(outputDirectoryName + "page_1.jpg");  // JPEG
stream.Save(outputDirectoryName + "page_1.bmp");  // BMP
Formato Estensione Cosa ottieni Usalo quando
PNG .png Senza perdita. I bordi del testo e le linee sottili rimangono nitidi. File più grandi. Pagine di documenti, anteprime dell'interfaccia, qualsiasi cosa con testo o diagrammi
JPEG .jpg Con perdita. Molto più piccoli. Nessuna trasparenza, e gli artefatti di compressione si notano attorno ai testi piccoli. Pagine fotografiche o scansionate, allegati e-mail, consegna con vincoli di dimensione
BMP .bmp Non compresso. Molto grandi. Pipeline legacy che richiedono specificamente bitmap non compresse

La regola pratica: se la pagina è prevalentemente testo, usa PNG. La compressione JPEG è ottimizzata per contenuti fotografici e, su una pagina ricca di testo, produce sbavature visibili attorno ai bordi dei glifi che nessuna impostazione di qualità riesce a eliminare del tutto. Se la pagina è una foto scansionata, JPEG ridurrà notevolmente la dimensione del file con un costo visivo minimo.


Impostare la risoluzione (DPI)

SaveAsImage esegue il rendering a 96 DPI per impostazione predefinita, che corrisponde a uno schermo tipico. È l'impostazione giusta per miniature e anteprime su schermo. Non è sufficiente quando qualcuno ingrandisce, stampa la pagina o inserisce l'immagine in un OCR.

Passa dpiX e dpiY per modificarla:

// 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();
}

La risoluzione non è un aggiornamento gratuito — il numero di pixel scala con il quadrato dei DPI, quindi il costo aumenta rapidamente:

DPI Numero di pixel relativo rispetto a 96 DPI Comparabile a Ragionevole per
96 (predefinito) 1× Schermo standard Miniature, anteprime inline, strisce di gallerie
150 ~2,4× Display Retina, zoom leggero Allegati e-mail, anteprime che gli utenti potrebbero ingrandire, stampa di bozze
300 ~9,8× Qualità di stampa Output di stampa, input OCR, master archivistici

Da quella tabella derivano due considerazioni. Primo, passare da 96 a 300 moltiplica il lavoro e l'archiviazione di circa dieci volte, quindi non ricorrere a 300 su un documento di 200 pagine a meno che qualcuno non lo stamperà davvero. Secondo, dpiX e dpiY sono argomenti separati per una ragione — normalmente vengono impostati sullo stesso valore, e impostarli diversamente allungherà la pagina.


Impacchettare o visualizzare in anteprima le immagini

Eseguire il rendering delle pagine è metà del lavoro; l'altra metà è farle arrivare all'utente. Tre schemi coprono quasi tutto.

Raggruppa tutto in un unico ZIP — l'approccio del primo esempio. Ideale quando l'utente vuole una cartella di file, e l'unica opzione che scala a dozzine di pagine senza tempestare il browser di richieste di download.

Scarica una singola immagine direttamente — non serve JSZip quando c'è un solo file:

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);

Mantieni le immagini all'interno della tua interfaccia React — nessun download. Questa è la scelta giusta per pannelli di anteprima e strisce di miniature, dove le immagini sono temporanee e una cartella di download piena di file page_1.png sarebbe solo disordine:

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;
};

Nota il dpiX: 72 nel caso dell'anteprima: le miniature non hanno bisogno della risoluzione completa, e renderizzarle più piccole mantiene la striscia reattiva. Ricorda di chiamare URL.revokeObjectURL(url) per ogni URL quando il componente viene smontato, altrimenti perderai memoria a ogni ri-renderizzazione.

Potrebbe interessarti anche: lavorare da un insieme di immagini anziché da un PDF — assemblare scansioni o foto in un unico documento? Si tratta di Convertire immagini in PDF in JavaScript (React).


Correggere il testo illeggibile: caricare i font

Di solito un PDF incorpora i font che utilizza, ma non sempre — e quando non lo fa, il renderer deve sostituirli con qualcos'altro. Nel browser non c'è una libreria di font del sistema operativo su cui fare affidamento, quindi un font mancante si trasforma in spazio vuoto o quadratini.

La soluzione è mettere il file del font dove il runtime WASM si aspetta di trovarlo prima di eseguire il rendering:

// Load a TrueType font into the VFS font directory before converting
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);

Vale la pena conoscere ARIALUNI.TTF: copre i caratteri CJK comuni oltre a quelli latini, il che lo rende il valore predefinito più sicuro quando i tuoi utenti caricano documenti in lingue che non hai enumerato. Se gestisci solo documenti in inglese, un font più piccolo mantiene il download più leggero.

Poiché questo viene eseguito prima che venga renderizzata qualsiasi pagina, un solo controllo dei font mancanti all'inizio della tua funzione di conversione è sufficiente — non è necessario ricaricare i font per ogni pagina.


Domande frequenti

La conversione di un PDF in immagini modifica il PDF originale?

No. SaveAsImage esegue il rendering delle pagine e restituisce nuovi dati immagine; il documento di origine viene aperto in sola lettura e rilasciato successivamente. Il tuo PDF originale rimane invariato.

Come faccio a convertire solo la prima pagina?

Chiama SaveAsImage una volta con pageIndex: 0 invece di usare un ciclo. Consulta Convertire solo pagine specifiche.

Perché il mio output è più grande del PDF originale?

Perché una pagina renderizzata memorizza pixel, mentre un PDF memorizza istruzioni di disegno. Una pagina PDF ricca di testo spesso pesa pochi kilobyte; un PNG a 300 DPI della stessa pagina può pesare megabyte. Passa a 96–150 DPI o usa JPEG se la dimensione conta più della fedeltà.

Posso mostrare le immagini nella mia app invece di scaricarle?

Sì — crea URL di oggetti dai dati immagine e usali come sorgenti <img>. Consulta Impacchettare o visualizzare in anteprima le immagini. Ricordati solo di revocare gli URL quando hai finito.

Un documento molto lungo causerà problemi?

Le pagine vengono renderizzate una alla volta all'interno del ciclo, quindi il modulo WASM mantiene all'incirca un'immagine di pagina alla volta anziché l'intero documento. Per file estremamente lunghi, converti a blocchi e aggiungi all'archivio man mano invece di conservare ogni immagine in un array.

Qual è la differenza tra convertire una pagina in un'immagine ed estrarre immagini da un PDF?

La conversione esegue il rendering dell'intera pagina — testo, layout, immagini, sfondi — come un'unica immagine piatta. L'estrazione preleva gli oggetti immagine originali incorporati nel documento alla loro risoluzione nativa. Usa la conversione per anteprime e condivisione; usa l'estrazione quando hai bisogno dell'opera grafica originale stessa.

Dove finiscono effettivamente i file convertiti?

Nel file system virtuale WASM, non sul tuo server né sul disco dell'utente. Nulla lascia il browser — l'unico modo in cui i file raggiungono l'utente è il passaggio di download o URL di oggetto che scrivi tu stesso.


Vedi anche

Cerchi la direzione opposta — trasformare le immagini di nuovo in un PDF? Si tratta di Convertire immagini in PDF in JavaScript (React). Il resto della pipeline delle pagine PDF in React: