Convierte documentos de Word a HTML en el navegador con JavaScript

2026-09-30 09:25: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 |

Convert Word to HTML in the browser

Los documentos de Word suelen ser el punto de partida para el contenido web: artículos, especificaciones de productos y documentos de cumplimiento, todo ello necesita eventualmente estar en un sitio web. Pasar de .docx a HTML limpio sin un servicio de conversión de backend es el desafío. Spire.Doc for JavaScript lo hace posible ejecutando un motor completo de procesamiento de documentos sobre WebAssembly, leyendo el archivo de Word a través de un sistema de archivos virtual (VFS), realizando la conversión localmente y permitiéndote descargar el HTML resultante, todo del lado del cliente, sin ida y vuelta al servidor.

Dos estrategias de exportación dominan el flujo de trabajo, y elegir entre ellas es la verdadera decisión:

  • Modo integrado empaqueta CSS e imágenes directamente en el archivo HTML, produciendo un único documento autocontenido que se abre en cualquier lugar.
  • Modo externo escribe CSS e imágenes en archivos separados, lo que te ofrece un HTML más pequeño, hojas de estilo reutilizables y recursos de imagen individuales que puedes gestionar de forma independiente.

Este artículo recorre ambos enfoques en un proyecto de React y los compara lado a lado. Para la configuración, consulta Integrar Spire.Doc for JavaScript en un proyecto de React. Los ejemplos a continuación asumen que Spire.Doc está instalado y que el módulo WebAssembly está inicializado.


Conversión básica: incrustar todo en un solo archivo

La forma más sencilla de publicar un documento de Word como página web es producir un único archivo HTML que contenga todo (marcado, estilos e imágenes) en un paquete autocontenido. Esto es ideal cuando necesitas un artefacto portátil que se represente correctamente sin importar dónde se abra, sin referencias a archivos faltantes ni enlaces rotos.

La conversión sigue tres pasos. Primero, carga el archivo de fuente y el documento de Word de origen en el sistema de archivos virtual de WASM usando FetchFileToVFS. Segundo, crea una instancia de Document, carga el archivo, configura HtmlExportOptions para incrustar tanto CSS como imágenes, y llama a SaveToFile para escribir el HTML. Tercero, lee el archivo generado desde VFS, envuélvelo en un Blob y activa una descarga del 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 generada a partir de un documento de Word mediante SaveToFile

HTML page generated from a Word document via SaveToFile


Opciones de exportación: CSS e imágenes separados

Incrustar todo en un solo archivo es cómodo, pero tiene ventajas y desventajas. Un documento grande con muchas imágenes produce un archivo HTML muy grande, y cada página que comparte el mismo estilo lleva su propia copia duplicada del CSS. Cuando quieres mantener los estilos de forma centralizada, reutilizar recursos de imagen en varias páginas o mantener pequeño el contenido HTML para una representación inicial más rápida, deberías exportar CSS e imágenes como archivos separados en su lugar.

HtmlExportOptions te ofrece un control detallado sobre cómo se escribe cada tipo de recurso. Puedes dirigir el CSS a un archivo de hoja de estilos con nombre, enviar las imágenes a un directorio dedicado e incluso controlar cómo se serializan los campos de formulario. El resultado ya no es un solo archivo, sino una estructura de directorios que contiene el HTML, la hoja de estilos y los archivos de imagen.

El flujo de trabajo es similar al del enfoque integrado, con dos añadidos. Antes de la conversión, crea un directorio de salida en VFS y usa CssStyleSheetFileName y ImagesPath para indicarle a Spire.Doc dónde escribir cada tipo de recurso. Después de la conversión, lee todo el directorio de salida de forma recursiva, empaqueta todo en un archivo zip usando JSZip y descárgalo en una sola operación.

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;

Archivos HTML, CSS e imágenes generados después de configurar las opciones de exportación

HTML, CSS, and image files generated after configuring the export options

Un detalle que vale la pena señalar: Spire.Doc no coloca las imágenes directamente en el directorio especificado por ImagesPath. En su lugar, crea una subcarpeta external_images dentro de ese directorio para contener los archivos de imagen. La estructura resultante es similar a Demo/external_images/*.png, y es por eso que addFilesToZip recorre el árbol de directorios de forma recursiva en lugar de leer una lista plana de archivos.


Integrado vs. externo: elegir la estrategia adecuada

Ambos modos de exportación producen HTML válido a partir del mismo documento de Word, pero responden a necesidades de publicación diferentes. La siguiente tabla resume las diferencias clave para ayudarte a decidir qué enfoque se adapta a tu flujo de trabajo.

Aspecto Integrado (archivo único) Externo (archivos separados)
Salida Un archivo .html con CSS en línea e imágenes Base64 HTML + .css + archivos de imagen en un directorio
Tamaño de archivo Más grande: todos los recursos se codifican en Base64 dentro del HTML HTML más pequeño; el tamaño total es similar, pero los recursos son archivos individuales
Portabilidad Totalmente autocontenido; se abre correctamente en cualquier lugar sin dependencias Requiere que todos los archivos permanezcan juntos; se deben conservar las rutas relativas
Mecanismo de descarga Descarga de un solo archivo mediante Blob Descarga de archivo zip (por ejemplo, con JSZip)
Reutilización de estilos Cada documento lleva su propia copia del CSS Varias páginas pueden compartir un único archivo de hoja de estilos
Gestión de imágenes Las imágenes son cadenas Base64 dentro del HTML; no se pueden referenciar ni almacenar en caché por separado Las imágenes son archivos individuales que se pueden almacenar en caché, cargar de forma diferida o reutilizar
Velocidad de representación inicial Más lenta para documentos grandes: el navegador debe analizar un archivo grande Análisis inicial del HTML más rápido; CSS e imágenes se cargan en paralelo
Ideal para Archivos adjuntos de correo electrónico, vistas previas puntuales, instantáneas de archivo, compartir un único documento Migración de contenido de CMS, publicación de varias páginas, bases de conocimiento, sitios con estilos compartidos
Mantenibilidad Baja: cambiar un estilo implica regenerar todo el archivo Alta: edita el archivo CSS una vez y todas las páginas vinculadas se actualizan

Guía rápida de decisión:

  • Elige el modo integrado cuando necesites un artefacto único y portátil; por ejemplo, generar una vista previa que un usuario descargue y abra sin conexión, o adjuntar un documento convertido a un correo electrónico.
  • Elige el modo externo cuando publiques en una plataforma web donde varios documentos compartan el mismo sistema de diseño, donde quieras almacenar en caché o cargar de forma diferida las imágenes, o donde el tamaño del archivo HTML sea importante para el rendimiento.

Preguntas frecuentes

Las fuentes en el HTML exportado no coinciden con el documento original

Si las fuentes en tu HTML convertido se ven diferentes del archivo de Word de origen, la causa casi siempre son datos de fuente faltantes en el sistema de archivos virtual de WASM. Spire.Doc depende de las fuentes cargadas en VFS para realizar cálculos precisos de diseño y resolución de nombres de fuentes durante la conversión. Cuando una fuente requerida no está disponible, el motor sustituye una fuente de reserva, y las declaraciones font-family en el CSS de salida no coincidirán con lo que especifica el documento original. En documentos que usan fuentes de símbolos como Wingdings, los caracteres afectados también pueden mostrarse como texto ilegible.

La solución es sencilla: precarga los archivos de fuente necesarios en VFS mediante FetchFileToVFS antes de ejecutar la conversión. Para documentos que contienen texto en chino, japonés o coreano, usa una fuente con amplia cobertura Unicode, como ARIALUNI.TTF:

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

El HTML exportado pierde sus estilos e imágenes al abrirlo

Cuando usas el modo externo (CssStyleSheetType.External con ImageEmbedded = false), los archivos CSS e imágenes se escriben en ubicaciones separadas, y el HTML los referencia mediante rutas relativas. Si descargas solo el archivo HTML sin sus recursos acompañantes, el navegador no puede resolver esas rutas y la página recurre a texto sin formato sin estilo con imágenes rotas.

Para evitar esto, empaqueta siempre el HTML junto con su directorio de recursos; el enfoque addFilesToZip que se muestra en la sección de opciones de exportación se encarga de esto al empaquetar todo en una única descarga zip. Como alternativa, si en realidad no necesitas archivos de recursos separados, cambia al modo integrado para que todo permanezca en un único archivo HTML autocontenido:

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

Ver también