Como Converter Páginas de PDF em Imagens em JavaScript (React)

2026-09-11 10:01:53 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

Você cria uma lista de documentos para um cliente, e o cliente pergunta: "posso ver as páginas antes de baixar?" Assim, de repente, você tem uma funcionalidade de renderização que não planejou. O mesmo pedido aparece em todo lugar — uma faixa de miniaturas sob uma caixa de entrada, um cartão de pré-visualização colado em um chat, um slide retirado de uma apresentação e publicado em redes sociais. Em todos os casos, um PDF não pode ser exibido em linha, mas uma imagem de suas páginas pode.

Depois de fazer essa mudança, quatro decisões determinam se o trabalho será útil: quais páginas, qual formato, quão nítidas e como os arquivos chegam ao usuário. A maioria dos exemplos de conversão de PDF para imagem responde apenas à primeira e deixa você descobrir o resto em produção.

Spire.PDF for JavaScript renderiza páginas no navegador por meio de WebAssembly e entrega cada página como um fluxo de imagem. Todas essas quatro decisões são suas para tomar, e cada uma é um único argumento ou uma extensão de arquivo alterada. Os arquivos entram e saem por meio de um sistema de arquivos virtual (VFS), então nada é enviado a lugar algum.

Neste artigo, você aprenderá como:

  • Renderizar todas as páginas de um PDF em PNG e baixar o conjunto como um ZIP
  • Limitar a conversão a uma única página ou a um intervalo de páginas
  • Alternar entre PNG, JPEG e BMP dependendo da finalidade da imagem
  • Equilibrar nitidez e tamanho de arquivo usando DPI
  • Entregar o resultado como um download, como arquivos individuais ou diretamente na sua interface React
  • Corrigir texto ilegível ou em branco causado por fontes ausentes

Pré-requisitos

Este tutorial pressupõe um projeto React com o Spire.PDF for JavaScript instalado e o módulo WASM inicializado. Para configuração, consulte Integrating Spire.PDF for JavaScript in a React Project.

Você precisará de:

  • Um PDF carregado no VFS
  • O módulo WASM acessível em window.wasmModule.spirepdf
  • O pacote jszip, se você quiser agrupar várias páginas em um único download (npm install jszip)

Converter todas as páginas em PNG

O caso do documento completo é o que você usará com mais frequência: abrir o PDF, percorrer cada página, renderizar cada uma em um fluxo, gravar cada fluxo em uma pasta no VFS e, em seguida, compactar essa pasta em ZIP e entregá-la ao navegador como 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;

Cada página do PDF exportada como uma imagem PNG via SaveAsImage e agrupada em um arquivo ZIP para download

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

O que o código faz:

  • doc.SaveAsImage({ pageIndex: i }) renderiza uma página e retorna um fluxo de imagem. Os índices de página começam em zero, então pageIndex: 0 é a primeira página.
  • stream.Save(outputFileName) grava esse fluxo no VFS. A extensão que você passa aqui define o formato — mais sobre isso abaixo.
  • stream.Dispose() libera o fluxo antes que a próxima página seja renderizada. Omiti-lo em um documento longo desperdiça memória sem nenhum benefício.
  • A sequência FS.mkdirTree → FS.readdir → FS.readFile existe porque o módulo WASM grava em seu próprio sistema de arquivos, não na pasta de downloads do navegador. O JSZip é o que transforma essa pasta em algo que o usuário pode salvar.
  • A renderização é somente leitura. O PDF de origem é aberto, lido e descartado; ele nunca é modificado.

Observação: Isso produz uma imagem de cada página, que é o que você quer para pré-visualizações, miniaturas e compartilhamento. Se, em vez disso, você quiser os arquivos de imagem originais incorporados dentro do PDF — o gráfico ou foto real em sua resolução nativa, não uma captura de tela da página em que ele está — essa é uma operação diferente: consulte Extract Images from a PDF in JavaScript (React).


Converter apenas páginas específicas

Renderizar um documento de 200 páginas para produzir três miniaturas é trabalho desperdiçado. Como a varredura de páginas é apenas um laço for sobre doc.Pages.Count, restringi-lo é uma questão de alterar os limites.

Uma única página — a capa ou um anexo específico:

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

Um intervalo contíguo — páginas 3 a 5, usando índices baseados em zero de 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();
}

Um conjunto escolhido manualmente — páginas que não são próximas umas das outras:

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

A verificação i < doc.Pages.Count é importante quando a lista de páginas vem da entrada do usuário em vez de uma constante fixa — um índice fora do intervalo é um erro em tempo de execução que você prefere não publicar.

Observe o (i + 1) nos nomes dos arquivos. Índices baseados em zero são corretos para a API e errados para humanos; nomear arquivos com o número da página que o usuário vê evita uma classe de tickets de suporte mais tarde.

Artigo recomendado: Quando você precisa dos objetos de imagem originais do PDF em vez de uma página renderizada — o gráfico ou foto incorporado em sua resolução nativa — consulte Extract Images from a PDF in JavaScript (React).


Escolher um formato de saída

O formato é decidido inteiramente pela extensão que você passa para stream.Save. Nada mais no fluxo de trabalho muda.

stream.Save(outputDirectoryName + "page_1.png");  // PNG
stream.Save(outputDirectoryName + "page_1.jpg");  // JPEG
stream.Save(outputDirectoryName + "page_1.bmp");  // BMP
Formato Extensão O que você obtém Use quando
PNG .png Sem perdas. Bordas de texto e linhas finas permanecem nítidas. Arquivos maiores. Páginas de documentos, pré-visualizações de interface, qualquer coisa com texto ou diagramas
JPEG .jpg Com perdas. Muito menor. Sem transparência, e artefatos de compressão aparecem ao redor de textos pequenos. Páginas fotográficas ou digitalizadas, anexos de e-mail, entrega com restrição de tamanho
BMP .bmp Sem compressão. Muito grande. Fluxos de trabalho legados que exigem especificamente bitmaps não comprimidos

A regra prática: se a página for predominantemente texto, use PNG. A compressão do JPEG é ajustada para conteúdo fotográfico e, em uma página com muito texto, produz borrões visíveis ao redor das bordas dos glifos que nenhum ajuste de qualidade remove completamente. Se a página for uma foto digitalizada, o JPEG reduzirá drasticamente o tamanho do arquivo com pouco custo visível.


Definir a resolução (DPI)

SaveAsImage renderiza a 96 DPI por padrão, o que corresponde a uma tela típica. Essa é a configuração correta para miniaturas e pré-visualizações na tela. Não é suficiente quando alguém amplia, imprime a página ou alimenta a imagem em um OCR.

Passe dpiX e dpiY para alterá-la:

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

A resolução não é uma melhoria gratuita — a contagem de pixels escala com o quadrado do DPI, então o custo aumenta rapidamente:

DPI Contagem de pixels relativa vs. 96 DPI Comparável a Razoável para
96 (padrão) 1× Tela padrão Miniaturas, pré-visualizações em linha, faixas de galeria
150 ~2,4× Tela Retina, zoom leve Anexos de e-mail, pré-visualizações que os usuários podem ampliar, impressão de rascunho
300 ~9,8× Qualidade de impressão Saída para impressão, entrada para OCR, masterizações de arquivo

Duas coisas decorrem dessa tabela. Primeiro, passar de 96 para 300 multiplica o trabalho e o armazenamento por aproximadamente dez, então não use 300 em um documento de 200 páginas a menos que alguém realmente vá imprimi-lo. Segundo, dpiX e dpiY são argumentos separados por um motivo — normalmente são definidos com o mesmo valor, e defini-los de forma diferente esticará a página.


Empacotar ou pré-visualizar as imagens

Renderizar as páginas é metade do trabalho; a outra metade é entregá-las ao usuário. Três padrões cobrem quase tudo.

Agrupar tudo em um único ZIP — a abordagem do primeiro exemplo. Melhor quando o usuário deseja uma pasta de arquivos, e a única opção que escala para dezenas de páginas sem sobrecarregar o navegador com solicitações de download.

Baixar uma única imagem diretamente — sem necessidade de JSZip quando há apenas um arquivo:

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

Manter as imagens dentro da sua interface React — sem download algum. Essa é a escolha certa para painéis de pré-visualização e faixas de miniaturas, onde as imagens são temporárias e uma pasta de downloads cheia de arquivos page_1.png seria apenas desordem:

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

Observe o dpiX: 72 no caso da pré-visualização: miniaturas não precisam de resolução total, e renderizá-las menores mantém a faixa responsiva. Lembre-se de chamar URL.revokeObjectURL(url) para cada URL quando o componente for desmontado, ou você vazará memória a cada nova renderização.

Você também pode gostar: Trabalhar a partir de um conjunto de imagens em vez de um PDF — montando digitalizações ou fotos em um único documento? Isso é Converting Images to PDF in JavaScript (React).


Corrigir texto ilegível: carregar fontes

Um PDF geralmente incorpora as fontes que usa, mas nem sempre — e quando não o faz, o renderizador precisa substituí-las por algo. No navegador, não há biblioteca de fontes do sistema operacional para recorrer, então uma fonte ausente se transforma em espaço em branco ou quadrados.

A solução é colocar o arquivo de fonte onde o tempo de execução WASM espera encontrá-lo antes de renderizar:

// 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 a pena conhecer o ARIALUNI.TTF: ele cobre caracteres CJK comuns, além de latinos, o que o torna a opção padrão mais segura quando seus usuários enviam documentos em idiomas que você não enumerou. Se você só lida com documentos em inglês, uma fonte menor mantém o download mais leve.

Como isso é executado antes de qualquer página ser renderizada, uma verificação de fonte ausente no início da sua função de conversão é suficiente — você não precisa recarregar fontes a cada página.


Perguntas frequentes

A conversão de um PDF em imagens altera o PDF original?

Não. SaveAsImage renderiza páginas e retorna novos dados de imagem; o documento de origem é aberto somente para leitura e descartado depois. Seu PDF original permanece intacto.

Como faço para converter apenas a primeira página?

Chame SaveAsImage uma vez com pageIndex: 0 em vez de fazer um laço. Consulte Converter apenas páginas específicas.

Por que minha saída é maior que o PDF original?

Porque uma página renderizada armazena pixels, enquanto um PDF armazena instruções de desenho. Uma página de PDF com muito texto costuma ter alguns kilobytes; um PNG de 300 DPI dessa mesma página pode ter megabytes. Reduza para 96–150 DPI ou mude para JPEG se o tamanho importar mais que a fidelidade.

Posso exibir as imagens no meu aplicativo em vez de baixá-las?

Sim — crie URLs de objeto a partir dos dados da imagem e use-as como fontes de <img>. Consulte Empacotar ou pré-visualizar as imagens. Apenas lembre-se de revogar as URLs quando terminar.

Um documento muito longo causará problemas?

As páginas são renderizadas uma de cada vez dentro do laço, então o módulo WASM mantém aproximadamente uma imagem de página por vez em vez do documento inteiro. Para arquivos extremamente longos, converta em blocos e acrescente ao arquivo à medida que avança, em vez de manter todas as imagens em um array.

Qual é a diferença entre converter uma página em imagem e extrair imagens de um PDF?

Converter renderiza a página inteira — texto, layout, imagens, fundos — como uma única imagem plana. Extrair retira os objetos de imagem originais incorporados no documento em sua resolução nativa. Use a conversão para pré-visualizações e compartilhamento; use a extração quando precisar da arte original em si.

Para onde os arquivos convertidos realmente vão?

Para o sistema de arquivos virtual do WASM, não para o seu servidor nem para o disco do usuário. Nada sai do navegador — a única forma de os arquivos chegarem ao usuário é a etapa de download ou URL de objeto que você mesmo escreve.


Veja também

Procurando a direção inversa — transformar imagens de volta em um PDF? Isso é Converting Images to PDF in JavaScript (React). O restante do fluxo de trabalho de páginas de PDF em React: