Converta Documentos Word em HTML no Navegador com JavaScript

2026-09-30 09:25:58 Allen Yang
AI Summarize:
ChatGPT
ChatGPT ✓
Claude ✓
Grok ✓
Perplexity ✓
Quick
Quick
Concise overview
Highlights
Key takeaways
Detailed
Structured explanation
Brief
One sentence summary
Summarize |

Converter Word para HTML no navegador

Documentos do Word são frequentemente o ponto de partida para conteúdo web — artigos, especificações de produtos e documentos de conformidade, todos precisam eventualmente estar em um site. Passar de .docx para HTML limpo sem um serviço de conversão em backend é o desafio. O Spire.Doc for JavaScript torna isso possível ao executar um mecanismo completo de processamento de documentos em WebAssembly, lendo o arquivo do Word por meio de um sistema de arquivos virtual (VFS), realizando a conversão localmente e permitindo que você baixe o HTML resultante — tudo no lado do cliente, sem ida e volta ao servidor.

Duas estratégias de exportação dominam o fluxo de trabalho, e escolher entre elas é a verdadeira decisão:

  • O modo Incorporado agrupa CSS e imagens diretamente no arquivo HTML, produzindo um único documento autocontido que abre em qualquer lugar.
  • O modo Externo grava CSS e imagens em arquivos separados, resultando em um HTML menor, folhas de estilo reutilizáveis e recursos de imagem individuais que você pode gerenciar de forma independente.

Este artigo percorre ambas as abordagens em um projeto React e as compara lado a lado. Para configuração, consulte Integrando o Spire.Doc for JavaScript em um Projeto React. Os exemplos abaixo pressupõem que o Spire.Doc está instalado e o módulo WebAssembly está inicializado.


Conversão Básica: Incorpore Tudo em Um Único Arquivo

A maneira mais simples de publicar um documento do Word como página web é produzir um único arquivo HTML que contenha tudo — marcação, estilos e imagens — em um pacote autocontido. Isso é ideal quando você precisa de um artefato portátil que seja renderizado corretamente onde quer que seja aberto, sem referências a arquivos ausentes ou links quebrados.

A conversão segue três etapas. Primeiro, carregue o arquivo de fonte e o documento de origem do Word no sistema de arquivos virtual do WASM usando FetchFileToVFS. Segundo, crie uma instância de Document, carregue o arquivo, configure HtmlExportOptions para incorporar tanto o CSS quanto as imagens e chame SaveToFile para gravar o HTML. Terceiro, leia o arquivo gerado de volta do VFS, envolva-o em um Blob e dispare o download pelo navegador.

function App() {
  const wordToHtml = async () => {
    // Get the Spire.Doc WASM module
    const docModule = window.wasmModule?.spiredoc;

    // Check if the module is ready
    if (!docModule) {
      alert('Spire.Doc is not ready yet');
      return;
    }

    // Load fonts and the Word file into VFS
    await window.spire.FetchFileToVFS('ARIALUNI.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/static/font/`);
    const inputFileName = 'ToHtml.docx';
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/static/data/`);

    // Load the Word document
    const wordDocument = new docModule.Document();
    wordDocument.LoadFromFile(inputFileName);

    // Embed the CSS styles into the HTML and embed images as Base64
    wordDocument.HtmlExportOptions.CssStyleSheetType = docModule.CssStyleSheetType.Internal;
    wordDocument.HtmlExportOptions.ImageEmbedded = true;

    // Convert the document to HTML
    const outputFileName = 'ToHtml-result.html';
    wordDocument.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Html });

    // Read the converted file from VFS and trigger download
    const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([fileArray], { type: 'text/html;charset=utf-8' });
    const url = URL.createObjectURL(blob);
    const a = window.document.createElement('a');
    a.href = url;
    a.download = outputFileName;
    a.click();
    URL.revokeObjectURL(url);

    // Release resources
    wordDocument.Dispose();
  };

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1>Convert Word To HTML</h1>
      <button onClick={wordToHtml}>
        Generate
      </button>
    </div>
  );
}

export default App;

Página HTML gerada a partir de um documento do Word via SaveToFile

Página HTML gerada a partir de um documento do Word via SaveToFile


Opções de Exportação: CSS e Imagens Separados

Incorporar tudo em um único arquivo é conveniente, mas tem suas desvantagens. Um documento grande com muitas imagens gera um arquivo HTML muito grande, e cada página que compartilha o mesmo estilo carrega sua própria cópia duplicada do CSS. Quando você quer manter estilos de forma centralizada, reutilizar recursos de imagem entre páginas ou manter o payload do HTML pequeno para uma renderização inicial mais rápida, deve exportar o CSS e as imagens como arquivos separados.

HtmlExportOptions oferece controle refinado sobre como cada tipo de recurso é gravado. Você pode direcionar o CSS para um arquivo de folha de estilo nomeado, enviar imagens para um diretório dedicado e até controlar como os campos de formulário são serializados. O resultado não é mais um único arquivo, mas uma estrutura de diretórios contendo o HTML, a folha de estilo e os arquivos de imagem.

O fluxo de trabalho espelha a abordagem incorporada, com dois acréscimos. Antes da conversão, crie um diretório de saída no VFS e use CssStyleSheetFileName e ImagesPath para informar ao Spire.Doc onde gravar cada tipo de recurso. Após a conversão, leia todo o diretório de saída recursivamente, empacote tudo em um arquivo zip usando JSZip e baixe-o em uma única operação.

import JSZip from 'jszip';

function App() {
  const wordToHtmlWithOptions = async () => {
    // Get the Spire.Doc WASM module
    const docModule = window.wasmModule?.spiredoc;

    // Check if the module is ready
    if (!docModule) {
      alert('Spire.Doc is not ready yet');
      return;
    }

    // Load fonts and the Word file into VFS
    await window.spire.FetchFileToVFS('ARIALUNI.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/static/font/`);
    const inputFileName = 'ToHtml.docx';
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/static/data/`);

    // Create the output directory in VFS
    const outputDirectoryName = 'ToHTMLFolder/';
    window.dotnetRuntime.Module.FS.mkdirTree(outputDirectoryName);

    // Load the Word document
    const wordDocument = new docModule.Document();
    wordDocument.LoadFromFile(inputFileName);

    // Export the CSS styles to a separate file
    wordDocument.HtmlExportOptions.CssStyleSheetFileName = outputDirectoryName + 'sample.css';
    wordDocument.HtmlExportOptions.CssStyleSheetType = docModule.CssStyleSheetType.External;

    // Export images to a separate directory
    wordDocument.HtmlExportOptions.ImageEmbedded = false;
    wordDocument.HtmlExportOptions.ImagesPath = outputDirectoryName + 'Demo/';

    // Export form fields as plain text
    wordDocument.HtmlExportOptions.IsTextInputFormFieldAsText = true;

    // Convert the document to HTML
    const outputFileName = 'ToHtmlExportOption-out.html';
    wordDocument.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Html });

    // Release resources
    wordDocument.Dispose();

    // Read the output directory recursively and write each level of files into the zip
    const zip = new JSZip();
    const addFilesToZip = async (folderPath, zipFolder) => {
      let items = await window.dotnetRuntime.Module.FS.readdir(folderPath);
      items = items.filter((item) => item !== '.' && item !== '..');
      for (const item of items) {
        const itemPath = `${folderPath}/${item}`;
        try {
          const fileData = await window.dotnetRuntime.Module.FS.readFile(itemPath);
          zipFolder.file(item, fileData);
        } catch (error) {
          const zipSubFolder = zipFolder.folder(item);
          await addFilesToZip(itemPath, zipSubFolder);
        }
      }
    };

    // Package the HTML file together with the resource directory
    zip.file(outputFileName, window.dotnetRuntime.Module.FS.readFile(outputFileName));
    await addFilesToZip(outputDirectoryName, zip);
    const zipBlob = await zip.generateAsync({ type: 'blob' });
    const url = URL.createObjectURL(zipBlob);

    // Trigger download
    const a = window.document.createElement('a');
    a.href = url;
    a.download = 'ToHTMLFolder.zip';
    a.click();
    URL.revokeObjectURL(url);
  };

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1>Convert Word To HTML With Export Options</h1>
      <button onClick={wordToHtmlWithOptions}>
        Generate
      </button>
    </div>
  );
}

export default App;

Arquivos HTML, CSS e de imagem gerados após configurar as opções de exportação

Arquivos HTML, CSS e de imagem gerados após configurar as opções de exportação

Um detalhe que vale a pena observar: o Spire.Doc não coloca as imagens diretamente no diretório especificado por ImagesPath. Em vez disso, ele cria uma subpasta external_images dentro desse diretório para armazenar os arquivos de imagem. A estrutura resultante se parece com Demo/external_images/*.png, e é por isso que addFilesToZip percorre a árvore de diretórios recursivamente em vez de ler uma lista simples de arquivos.


Incorporado vs. Externo: Escolhendo a Estratégia Certa

Ambos os modos de exportação produzem HTML válido a partir do mesmo documento do Word, mas atendem a necessidades de publicação diferentes. A tabela abaixo resume as principais diferenças para ajudá-lo a decidir qual abordagem se encaixa no seu fluxo de trabalho.

Aspecto Incorporado (Arquivo Único) Externo (Arquivos Separados)
Saída Um arquivo .html com CSS embutido e imagens em Base64 HTML + .css + arquivos de imagem em um diretório
Tamanho do arquivo Maior — todos os recursos são codificados em Base64 dentro do HTML HTML menor; o tamanho total é semelhante, mas os recursos são arquivos individuais
Portabilidade Totalmente autocontido; abre corretamente em qualquer lugar, sem dependências Requer que todos os arquivos permaneçam juntos; os caminhos relativos devem ser preservados
Mecanismo de download Download de arquivo único via Blob Download de arquivo zip (por exemplo, com JSZip)
Reutilização de estilo Cada documento carrega sua própria cópia do CSS Várias páginas podem compartilhar um único arquivo de folha de estilo
Gerenciamento de imagens As imagens são strings Base64 dentro do HTML; não podem ser referenciadas ou armazenadas em cache separadamente As imagens são arquivos individuais que podem ser armazenados em cache, carregados sob demanda ou reutilizados
Velocidade de renderização inicial Mais lenta para documentos grandes — o navegador precisa processar um único arquivo grande Análise inicial do HTML mais rápida; CSS e imagens carregam em paralelo
Ideal para Anexos de e-mail, pré-visualizações pontuais, capturas para arquivamento, compartilhamento de um único documento Migração de conteúdo de CMS, publicação em várias páginas, bases de conhecimento, sites com estilos compartilhados
Manutenibilidade Baixa — alterar um estilo significa regenerar todo o arquivo Alta — edite o arquivo CSS uma vez e todas as páginas vinculadas são atualizadas

Guia de decisão rápida:

  • Escolha o modo incorporado quando precisar de um artefato único e portátil — por exemplo, gerar uma pré-visualização que o usuário baixa e abre offline, ou anexar um documento convertido a um e-mail.
  • Escolha o modo externo quando estiver publicando em uma plataforma web onde vários documentos compartilham o mesmo sistema de design, onde você deseja armazenar imagens em cache ou carregá-las sob demanda, ou onde o tamanho do arquivo HTML importa para o desempenho.

Perguntas Frequentes

As fontes no HTML exportado não correspondem ao documento original

Se as fontes no HTML convertido parecerem diferentes do arquivo Word de origem, a causa é quase sempre a ausência de dados de fonte no sistema de arquivos virtual do WASM. O Spire.Doc depende de fontes carregadas no VFS para realizar cálculos precisos de layout e resolução de nomes de fontes durante a conversão. Quando uma fonte necessária não está disponível, o mecanismo substitui por uma fonte alternativa, e as declarações font-family no CSS de saída não corresponderão ao que o documento original especifica. Para documentos que usam fontes de símbolos, como Wingdings, os caracteres afetados também podem ser renderizados como texto ilegível.

A correção é simples: pré-carregue os arquivos de fonte necessários no VFS via FetchFileToVFS antes de executar a conversão. Para documentos que contêm texto em chinês, japonês ou coreano, use uma fonte com ampla cobertura Unicode, como ARIALUNI.TTF:

await window.spire.FetchFileToVFS(
  'ARIALUNI.TTF', '/Library/Fonts/', '/'
);

O HTML exportado perde seus estilos e imagens ao ser aberto

Quando você usa o modo externo (CssStyleSheetType.External com ImageEmbedded = false), os arquivos CSS e de imagem são gravados em locais separados, e o HTML os referencia por meio de caminhos relativos. Se você baixar apenas o arquivo HTML sem seus recursos acompanhantes, o navegador não conseguirá resolver esses caminhos e a página será exibida como texto simples sem estilo e com imagens quebradas.

Para evitar isso, sempre empacote o HTML junto com seu diretório de recursos — a abordagem addFilesToZip mostrada na seção de opções de exportação faz isso agrupando tudo em um único download zip. Como alternativa, se você não precisa realmente de arquivos de recursos separados, mude para o modo incorporado para que tudo permaneça em um único arquivo HTML autocontido:

wordDocument.HtmlExportOptions.CssStyleSheetType = docModule.CssStyleSheetType.Internal;
wordDocument.HtmlExportOptions.ImageEmbedded = true;

Veja Também