
Vous créez une liste de documents pour un client, et le client demande : « puis-je voir les pages avant de télécharger ? » Aussitôt, vous vous retrouvez avec une fonctionnalité de rendu que vous n'aviez pas prévue. La même demande surgit partout — une bande de vignettes sous une boîte de réception, une carte d'aperçu collée dans une conversation, une diapositive extraite d'un diaporama et publiée sur les réseaux sociaux. Dans tous les cas, un PDF ne peut pas être affiché en ligne, mais une image de ses pages le peut.
Une fois ce basculement opéré, quatre décisions déterminent si le travail est exploitable : quelles pages, quel format, quelle netteté, et comment les fichiers parviennent à l'utilisateur. La plupart des exemples de conversion PDF en image ne répondent qu'à la première et vous laissent découvrir le reste en production.
Spire.PDF for JavaScript effectue le rendu des pages dans le navigateur via WebAssembly et vous fournit chaque page sous forme de flux d'image. Ces quatre décisions vous appartiennent, et chacune se résume à un seul argument ou à une extension de fichier modifiée. Les fichiers entrent et sortent via un système de fichiers virtuel (VFS), donc rien n'est téléversé où que ce soit.
Dans cet article, vous apprendrez à :
- Effectuer le rendu de chaque page d'un PDF en PNG et télécharger l'ensemble sous forme de ZIP
- Limiter la conversion à une seule page ou à une plage de pages
- Basculer entre PNG, JPEG et BMP selon l'usage prévu de l'image
- Arbitrer entre netteté et taille de fichier à l'aide du DPI
- Livrer le résultat sous forme de téléchargement, de fichiers individuels, ou directement dans votre interface React
- Corriger le texte illisible ou vide causé par des polices manquantes
Prérequis
Ce guide suppose un projet React avec Spire.PDF for JavaScript installé et le module WASM initialisé. Pour l'installation, consultez Intégrer Spire.PDF for JavaScript dans un projet React.
Vous aurez besoin de :
- Un PDF chargé dans le VFS
- Le module WASM accessible à
window.wasmModule.spirepdf - Le paquet
jszip, si vous souhaitez regrouper plusieurs pages en un seul téléchargement (npm install jszip)
Convertir chaque page en PNG
Le cas du document complet est celui auquel vous aurez le plus souvent recours : ouvrez le PDF, parcourez chaque page, effectuez le rendu de chacune vers un flux, écrivez chaque flux dans un dossier du VFS, puis compressez ce dossier en ZIP et remettez-le au navigateur sous forme de téléchargement.
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;
Chaque page du PDF exportée sous forme d'image PNG via SaveAsImage et regroupée dans un fichier ZIP à télécharger

Ce que fait le code :
-
doc.SaveAsImage({ pageIndex: i })effectue le rendu d'une page et renvoie un flux d'image. Les index de page sont basés sur zéro, doncpageIndex: 0correspond à la première page. -
stream.Save(outputFileName)écrit ce flux dans le VFS. L'extension que vous indiquez ici définit le format — nous y reviendrons ci-dessous. -
stream.Dispose()libère le flux avant le rendu de la page suivante. L'omettre sur un document long gaspille de la mémoire sans aucun bénéfice. - La séquence
FS.mkdirTree→FS.readdir→FS.readFileexiste parce que le module WASM écrit dans son propre système de fichiers, et non dans le dossier de téléchargement du navigateur. C'est JSZip qui transforme ce dossier en quelque chose que l'utilisateur peut enregistrer. - Le rendu est en lecture seule. Le PDF source est ouvert, lu et libéré ; il n'est jamais modifié.
Remarque : Cela produit une image de chaque page, ce que vous voulez pour les aperçus, les vignettes et le partage. Si vous souhaitez plutôt les fichiers image d'origine intégrés dans le PDF — le graphique ou la photo réels à leur résolution native, et non une capture d'écran de la page qui les contient — il s'agit d'une opération différente : consultez Extraire des images d'un PDF en JavaScript (React).
Convertir uniquement des pages spécifiques
Effectuer le rendu d'un document de 200 pages pour produire trois vignettes est un travail inutile. Comme le parcours des pages n'est qu'une boucle for sur doc.Pages.Count, le restreindre revient simplement à modifier les bornes.
Une seule page — la couverture ou une annexe précise :
// Render only the first page
const outputFileName = outputDirectoryName + "cover.png";
let stream = doc.SaveAsImage({ pageIndex: 0 });
stream.Save(outputFileName);
stream.Dispose();
Une plage contiguë — les pages 3 à 5, en utilisant les index basés sur zéro 2 à 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 ensemble choisi manuellement — des pages qui ne se suivent pas :
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();
}
La garde i < doc.Pages.Count importe lorsque la liste des pages provient d'une saisie utilisateur plutôt que d'une constante codée en dur — un index hors limites est une erreur d'exécution que vous préférez ne pas livrer.
Remarquez le (i + 1) dans les noms de fichiers. Les index basés sur zéro conviennent à l'API mais pas aux humains ; nommer les fichiers d'après le numéro de page que l'utilisateur voit évite toute une catégorie de tickets de support par la suite.
Article recommandé : Lorsque vous avez besoin des objets image d'origine contenus dans le PDF plutôt que d'une page rendue — le graphique ou la photo intégrés à leur résolution native — consultez Extraire des images d'un PDF en JavaScript (React).
Choisir un format de sortie
Le format est entièrement déterminé par l'extension que vous passez à stream.Save. Rien d'autre dans le pipeline ne change.
stream.Save(outputDirectoryName + "page_1.png"); // PNG
stream.Save(outputDirectoryName + "page_1.jpg"); // JPEG
stream.Save(outputDirectoryName + "page_1.bmp"); // BMP
| Format | Extension | Ce que vous obtenez | À privilégier lorsque |
|---|---|---|---|
| PNG | .png |
Sans perte. Les contours du texte et les lignes fines restent nets. Fichiers plus volumineux. | Pages de documents, aperçus d'interface, tout contenu comportant du texte ou des schémas |
| JPEG | .jpg |
Avec perte. Bien plus petits. Pas de transparence, et des artefacts de compression apparaissent autour des petits textes. | Pages photographiques ou numérisées, pièces jointes, livraison contrainte en taille |
| BMP | .bmp |
Non compressé. Très volumineux. | Pipelines hérités exigeant spécifiquement des bitmaps non compressés |
La règle pratique : si la page est essentiellement composée de texte, utilisez PNG. La compression JPEG est optimisée pour le contenu photographique et, sur une page riche en texte, elle produit un brouillage visible autour des contours des glyphes qu'aucun réglage de qualité ne parvient à éliminer complètement. Si la page est une photo numérisée, JPEG réduira considérablement la taille du fichier avec peu de perte visible.
Définir la résolution (DPI)
SaveAsImage effectue le rendu à 96 DPI par défaut, ce qui correspond à un écran classique. C'est le bon réglage pour les vignettes et les aperçus à l'écran. Ce n'est pas suffisant quand quelqu'un zoome, imprime la page ou soumet l'image à un OCR.
Passez dpiX et dpiY pour le modifier :
// 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 résolution n'est pas une amélioration gratuite — le nombre de pixels évolue avec le carré du DPI, donc le coût grimpe rapidement :
| DPI | Nombre de pixels relatif par rapport à 96 DPI | Comparable à | Raisonnable pour |
|---|---|---|---|
| 96 (par défaut) | 1× | Écran standard | Vignettes, aperçus intégrés, bandes de galerie |
| 150 | ~2,4× | Écran Retina, léger zoom | Pièces jointes, aperçus que les utilisateurs peuvent zoomer, impression de brouillon |
| 300 | ~9,8× | Qualité d'impression | Sortie d'impression, entrée OCR, masters d'archivage |
Deux conséquences découlent de ce tableau. Premièrement, passer de 96 à 300 multiplie le travail et le stockage par environ dix, donc n'optez pas pour 300 sur un document de 200 pages à moins que quelqu'un ait réellement l'intention de l'imprimer. Deuxièmement, dpiX et dpiY sont des arguments distincts pour une raison — ils sont normalement définis à la même valeur, et les définir différemment étirera la page.
Empaqueter ou prévisualiser les images
Effectuer le rendu des pages ne représente que la moitié du travail ; l'autre moitié consiste à les transmettre à l'utilisateur. Trois modèles couvrent presque tous les cas.
Tout regrouper dans un seul ZIP — l'approche du premier exemple. Idéal lorsque l'utilisateur souhaite un dossier de fichiers, et seule option qui passe à l'échelle pour des dizaines de pages sans submerger le navigateur de demandes de téléchargement.
Télécharger une seule image directement — JSZip n'est pas nécessaire lorsqu'il n'y a qu'un seul fichier :
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);
Conserver les images dans votre interface React — aucun téléchargement. C'est le bon choix pour les panneaux d'aperçu et les bandes de vignettes, où les images sont temporaires et où un dossier de téléchargement rempli de fichiers page_1.png ne serait qu'encombrement :
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;
};
Remarquez le dpiX: 72 dans le cas de l'aperçu : les vignettes n'ont pas besoin de la pleine résolution, et les rendre plus petites garde la bande réactive. N'oubliez pas d'appeler URL.revokeObjectURL(url) pour chaque URL lorsque le composant est démonté, sinon vous fuirez de la mémoire à chaque nouveau rendu.
Vous aimerez peut-être aussi : Vous partez d'un ensemble d'images plutôt que d'un PDF — vous assemblez des numérisations ou des photos en un seul document ? C'est Convertir des images en PDF en JavaScript (React).
Corriger le texte illisible : charger les polices
Un PDF intègre généralement les polices qu'il utilise, mais pas toujours — et lorsqu'il ne le fait pas, le moteur de rendu doit substituer quelque chose. Dans le navigateur, aucune bibliothèque de polices du système d'exploitation ne peut servir de repli, donc une police manquante se transforme en espaces vides ou en carrés.
La solution consiste à placer le fichier de police là où le runtime WASM s'attend à le trouver avant d'effectuer le rendu :
// 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 vaut la peine d'être connu : il couvre les caractères CJK courants ainsi que le latin, ce qui en fait la valeur par défaut la plus sûre lorsque vos utilisateurs téléversent des documents dans des langues que vous n'avez pas énumérées. Si vous ne traitez que des documents en anglais, une police plus petite allège le téléchargement.
Comme cela s'exécute avant le rendu de toute page, une seule vérification des polices manquantes au début de votre fonction de conversion suffit — vous n'avez pas besoin de recharger les polices page par page.
FAQ
La conversion d'un PDF en images modifie-t-elle le PDF d'origine ?
Non. SaveAsImage effectue le rendu des pages et renvoie de nouvelles données d'image ; le document source est ouvert en lecture seule puis libéré. Votre PDF d'origine reste intact.
Comment convertir uniquement la première page ?
Appelez SaveAsImage une seule fois avec pageIndex: 0 au lieu de boucler. Voir Convertir uniquement des pages spécifiques.
Pourquoi ma sortie est-elle plus volumineuse que le PDF d'origine ?
Parce qu'une page rendue stocke des pixels, tandis qu'un PDF stocke des instructions de dessin. Une page PDF riche en texte ne pèse souvent que quelques kilo-octets ; un PNG de cette même page à 300 DPI peut atteindre plusieurs méga-octets. Passez à 96–150 DPI ou optez pour JPEG si la taille importe plus que la fidélité.
Puis-je afficher les images dans mon application au lieu de les télécharger ?
Oui — créez des URL d'objet à partir des données d'image et utilisez-les comme sources <img>. Voir Empaqueter ou prévisualiser les images. Pensez simplement à révoquer les URL une fois terminé.
Un document très long posera-t-il des problèmes ?
Les pages sont rendues une à la fois dans la boucle, donc le module WASM ne conserve globalement qu'une image de page à la fois plutôt que le document entier. Pour les fichiers extrêmement longs, convertissez par blocs et ajoutez à l'archive au fur et à mesure plutôt que de conserver toutes les images dans un tableau.
Quelle est la différence entre convertir une page en image et extraire les images d'un PDF ?
La conversion effectue le rendu de la page entière — texte, mise en page, images, arrière-plans — sous forme d'une seule image aplatie. L'extraction récupère les objets image d'origine intégrés dans le document à leur résolution native. Utilisez la conversion pour les aperçus et le partage ; utilisez l'extraction lorsque vous avez besoin de l'illustration source elle-même.
Où vont réellement les fichiers convertis ?
Dans le système de fichiers virtuel WASM, ni sur votre serveur ni sur le disque de l'utilisateur. Rien ne quitte le navigateur — la seule façon pour les fichiers d'atteindre l'utilisateur est l'étape de téléchargement ou d'URL d'objet que vous écrivez vous-même.
Voir aussi
Vous cherchez la direction inverse — reconvertir des images en PDF ? C'est Convertir des images en PDF en JavaScript (React). Le reste du pipeline de pages PDF dans React :