Convert Word to Image with JavaScript in React

Converting a Word document to images is the most common approach for online preview, thumbnail generation, and preventing content from being copied at will — the resulting images keep a consistent layout on any device. Spire.Doc for JavaScript performs this conversion directly in the browser via WebAssembly, managing input and output files through a virtual file system (VFS) — no backend server required.

This article covers two core features:

For installation and project setup, refer to Integrating Spire.Doc for JavaScript in a React Project. The examples below assume Spire.Doc is installed and the WebAssembly module is initialized.


Page to Image

Converting a document page to an image involves three stages: first, load the font file and the target Word document into the WASM virtual file system via FetchFileToVFS; then instantiate a Document, load the document, call SaveImageToStreams with a pageIndex to render the specified page as an image, and save it to VFS; finally, read the generated image file from VFS, wrap it as a Blob, and create a download link.

import React from 'react';

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

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

    // Load the font file into the virtual file system (VFS)
    await window.spire.FetchFileToVFS('ARIALUNI.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
    const inputFileName = 'ToImage.docx';
    // Load the target Word document into VFS
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);

    // Create a Document instance and load the document
    const doc = new docModule.Document();
    doc.LoadFromFile(inputFileName);

    // Define the output file name
    const outputFileName = "ToImage-result.png";

    // Convert the first page to an image stream and save it to VFS
    let img = doc.SaveImageToStreams({ pageIndex: 0, type: docModule.ImageType.Bitmap });
    img.Save(outputFileName);

    // Release resources
    doc.Dispose();

    // Read the generated file from VFS and wrap it as a Blob
    const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([modifiedFileArray], {  type: 'image/png'});
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = outputFileName;
    a.click();
    URL.revokeObjectURL(url);
  };

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1>Convert a Specified Page to an Image</h1>
      <button onClick={ToImage}>
        Generate
      </button>
    </div>
  );
}

export default App;

PNG image generated from a document page via SaveImageToStreams

PNG image generated from a document page via SaveImageToStreams


Document Object to Image

Besides whole-page conversion, real projects often need to export a single element of a document as an image — for example, generating a preview image for a table, or extracting a shape from a document as standalone material. Paragraphs, tables, table rows, table cells, and shapes can all be copied into a newly created Document via the Clone method, and then rendered into an image with SaveImageToStreams. The conversion results are written uniformly to an output directory in VFS, and finally packaged into a single ZIP file with JSZip for the user to download.

Note that a shape cannot be added directly to a paragraph of a newly created document. The example first saves the document to a memory stream and then reloads it, so that the shape obtains a complete layout context in the new document before being rendered.

import React from 'react';
import JSZip from "jszip";

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

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

    // Load the font file into the virtual file system (VFS)
    await window.spire.FetchFileToVFS('ARIALUNI.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
    // Load the target Word document into VFS
    const inputFileName = "ConvertObjectToImage.docx";
    await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);

    // Define and create the output directory in VFS
    const outputDirectoryName = "outputFolder/";
    await window.dotnetRuntime.Module.FS.mkdirTree(outputDirectoryName);

    // Create a Document instance and load the document
    const doc = new docModule.Document();
    doc.LoadFromFile(inputFileName);

    // Get the first section and its body
    let section = doc.Sections.get_Item(0);
    let body = section.Body;

    // Get the first paragraph and convert it to an image
    let paragraph = body.Paragraphs.get_Item(0);
    let imageStream1 = ConvertParagraphToImage(paragraph, docModule);
    let imageFile1 = outputDirectoryName + "ConvertParagraphToImage.png";
    window.dotnetRuntime.Module.FS.writeFile(imageFile1, imageStream1.Save());

    // Get the first table and convert it to an image
    let table = body.Tables.get_Item(0);
    let imageStream2 = ConvertTableToImage(table, docModule);
    let imageFile2 = outputDirectoryName + "ConvertTableToImage.jpg";
    window.dotnetRuntime.Module.FS.writeFile(imageFile2, imageStream2.Save());

    // Get the first row of the first table and convert it to an image
    let row = table.Rows.get_Item(0);
    let imageStream3 = ConvertTableRowToImage(row, docModule);
    let imageFile3 = outputDirectoryName + "ConvertTableRowToImage.bmp";
    window.dotnetRuntime.Module.FS.writeFile(imageFile3, imageStream3.Save());

    // Get the first cell of the first row and convert it to an image
    let cell = row.Cells.get_Item(0);
    let imageStream4 = ConvertTableCellToImage(cell, docModule);
    let imageFile4 = outputDirectoryName + "ConvertTableCellToImage.png";
    window.dotnetRuntime.Module.FS.writeFile(imageFile4, imageStream4.Save());

    // Iterate over the paragraphs and convert the shapes in them to images
    for (let i = 0; i < section.Paragraphs.Count; i++) {
      let para = section.Body.Paragraphs.get_Item(i);
      for (let j = 0; j < para.ChildObjects.Count; j++) {
        let docObj = para.ChildObjects.get_Item(j);
        if (docObj.DocumentObjectType == docModule.DocumentObjectType.Shape) {
          let imageStream5 = ConvertShapeToImage(docObj, docModule);
          let imageFile5 = outputDirectoryName + "ConvertShapeToImage-" + j + ".png";

          window.dotnetRuntime.Module.FS.writeFile(imageFile5, imageStream5.Save());
          i++;
        }
      }
    }

    // Release resources
    doc.Dispose();

    // Package all images in the output directory into a ZIP file
    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);
        }
      }
    };

    await addFilesToZip(outputDirectoryName, zip);
    const zipBlob = await zip.generateAsync({ type: "blob" });
    // Read the generated file from VFS and wrap it as a Blob
    const url = URL.createObjectURL(zipBlob);
    const a = document.createElement('a');
    a.href = url;
    a.download = "ConvertObjectToImage_out.zip";
    a.click();
    URL.revokeObjectURL(url);
  };

  // Convert a paragraph to an image
  function ConvertParagraphToImage(paragraph, docModule) {
    let doc = new docModule.Document();
    let section = doc.AddSection();

    section.Body.ChildObjects.Add(paragraph.Clone());
    let imageStream = doc.SaveImageToStreams({ pageIndex: 0, type: docModule.ImageType.Bitmap });
    doc.Close();
    return imageStream;
  }

  // Convert a table to an image
  function ConvertTableToImage(table, docModule) {
    let doc = new docModule.Document();
    let section = doc.AddSection();

    section.Body.ChildObjects.Add(table.Clone());

    let imageStream = doc.SaveImageToStreams({ pageIndex: 0, type: docModule.ImageType.Bitmap });
    doc.Close();
    return imageStream;
  }

  // Convert a table row to an image
  function ConvertTableRowToImage(tableRow, docModule) {
    let doc = new docModule.Document();
    let section = doc.AddSection();
    let table = section.AddTable();
    table.Rows.Add(tableRow.Clone());
    let imageStream = doc.SaveImageToStreams({ pageIndex: 0, type: docModule.ImageType.Bitmap });
    doc.Close();
    return imageStream;
  }

  // Convert a table cell to an image
  function ConvertTableCellToImage(tableCell, docModule) {
    let doc = new docModule.Document();
    let section = doc.AddSection();
    let table = section.AddTable();
    table.AddRow().Cells.Add(tableCell.Clone());
    let imageStream = doc.SaveImageToStreams({ pageIndex: 0, type: docModule.ImageType.Bitmap });
    doc.Close();
    return imageStream;
  }

  // Convert a shape to an image
  function ConvertShapeToImage(shape, docModule) {
    let doc = new docModule.Document();
    let section = doc.AddSection();
    section.AddParagraph().ChildObjects.Add(shape.Clone());
    let memoryStream = new docModule.Stream();
    doc.SaveToStream({ stream: memoryStream, fileFormat: docModule.FileFormat.Docx });
    doc.LoadFromStream({ stream: memoryStream, fileFormat: docModule.FileFormat.Docx });
    let imageStream = doc.SaveImageToStreams({ pageIndex: 0, type: docModule.ImageType.Bitmap });
    memoryStream.Close();
    doc.Close();
    return imageStream;
  }

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1>Convert Elements to Images</h1>
      <button onClick={ToImage}>
        Generate
      </button>
    </div>
  );
}

export default App;

Images inside the ZIP file generated after converting the document objects

Images inside the ZIP file generated after converting the document objects


FAQ

Missing or garbled text in the generated image

Cause: The font files required for rendering are missing from the WASM virtual file system. SaveImageToStreams reads fonts from VFS when rendering text — if they are not preloaded, text areas will be left blank or appear garbled.

Solution: Load the font files into VFS via FetchFileToVFS before conversion:

await window.spire.FetchFileToVFS(
  'ARIALUNI.TTF', '/Library/Fonts/', 
  `${process.env.PUBLIC_URL}/static/font/`
);

Only the first page is generated

Cause: Each call to SaveImageToStreams renders only the single page specified by pageIndex. The example always passes 0, so a multi-page document only outputs an image of the first page.

Solution: Get the total page count via PageCount and iterate page by page, generating a separate image file for each page:

for (let i = 0; i < doc.PageCount; i++) {
  let img = doc.SaveImageToStreams({
    pageIndex: i, type: wasmModule.ImageType.Bitmap
  });
  img.Save(`ToImage-page-${i + 1}.png`);
}

Get a Free License

If you wish to remove the evaluation message from the resulting document, or to eliminate functional limitations, please contact our sales team to request a 30-day temporary license.