Share via

Header image(s) broken in document after using Office.context.document.getFileAsync with Office.FileType.Compressed

Rajat Bharadwaj 5 Reputation points
2026-01-30T13:58:02.9666667+00:00

I am trying a usecase where requirement to upload the open document via addin using REST API which accepts base64 of word document.

I used Office.context.document.getFileAsync function passing input as "Office.FileType.Compressed".
But the base64 response using above usecase results in below issues

  1. Header images in base64 (output from function) is broken.

I saw below actions taking place

  1. Images name under media folder is renamed from "imageheader1.png" to "image1.png" but in "header1.xml.rels" file under word/_rels folder image is being pinted to old image name itself
    "imageheader1.png" as mentioned below.

Please help how can i fix this issue? As header image comes as broken when opening a document using the base64.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
	<Relationship Id="rId1" Target="ooxWord://word/media/imageheader1.png" TargetMode="External" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"/>
</Relationships>
Microsoft 365 and Office | Development | Office JavaScript API
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Matthew-P 11,575 Reputation points Microsoft External Staff Moderator
    2026-01-30T14:53:26.8966667+00:00

    Hi Rajat Bharadwaj

    Welcome to Microsoft Q&A Forum!

    I completely understand the issue you are facing. It appears to be a limitation in how Office.context.document.getFileAsync packages the OOXML (.docx) file, particularly for images in headers when the document is in-memory or unsaved. The "ooxWord://" scheme you are seeing is an internal Word representation that hasn't been resolved to a standard relative path yet.

    Here is a solution that implements this fix: 

    1. Save the Document Before Exporting

    If the document hasn't been saved to disk (e.g., it's a new or modified unsaved file), the internal references may not resolve properly. Try saving it first to force Word to embed and update resources correctly:

    • Prompt the user to save the document manually (via File > Save) before triggering the upload.
    • Test if getFileAsync then produces a valid package with correct rels (no "ooxWord://" or mismatches).
    • Note: There's no direct saveAsync API in Word's Office.js for automatic saving. If this is a frequent issue, consider checking the document's URL via Office.context.document.url to see if it's saved (a non-empty URL indicates it's on disk/OneDrive).

    If saving resolves it, integrate a user prompt or workflow step in your add-in.

    2. Post-Process the OOXML Package

    If forcing a save isn't feasible or doesn't solve it completely, you need to modify the compressed file client-side before uploading. You can use JSZipto unpack the file, fix the broken relationships in the headers, and repack it.

    Note: Microsoft is providing this information as a convenience to you. These sites are not controlled by Microsoft, and Microsoft cannot make any representations regarding the quality, safety, or suitability of any software or information found there. Please ensure that you fully understand the risks before using any suggestions from the above link.

    Here is the code implementation using JSZip:

    async function fixHeaderImages(fileData) { 
      const zip = new JSZip(); 
      await zip.loadAsync(fileData); 
      
      // Iterate over potential header rels files (header1.xml.rels, header2.xml.rels, etc.) 
      // Adjust loop limit based on expected max headers in your documents 
      for (let i = 1; i <= 10; i++) {  
        const relsPath = `word/_rels/header${i}.xml.rels`; 
     
        if (zip.file(relsPath)) { 
          let relsXml = await zip.file(relsPath).async('string'); 
      
          // Parse the XML (use DOMParser for browser compatibility) 
          const parser = new DOMParser(); 
          const xmlDoc = parser.parseFromString(relsXml, 'application/xml'); 
      
          // Find all image relationships 
          const relationships = xmlDoc.getElementsByTagName('Relationship'); 
     
          for (let rel of relationships) { 
            const type = rel.getAttribute('Type'); 
     
            // Check if it is an image relationship 
            if (type === 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image') { 
              let target = rel.getAttribute('Target'); 
     
              // Check for the specific broken schema 
              if (target && target.startsWith('ooxWord://word/media/imageheader')) { 
     
                // Extract number (e.g., "1" from "imageheader1.png") 
                const match = target.match(/imageheader(\d+)\.png/); 
     
                if (match) { 
                  const num = match[1]; 
                  // Update to internal relative path (assumes renaming strips "header" and keeps number) 
                  rel.setAttribute('Target', `../media/image${num}.png`); 
                  rel.removeAttribute('TargetMode');  // Defaults to internal 
                } 
              } 
            } 
          } 
      
          // Serialize back to string 
          const serializer = new XMLSerializer(); 
          relsXml = serializer.serializeToString(xmlDoc); 
      
          // Replace the file in the zip 
          zip.file(relsPath, relsXml); 
        } 
      } 
      
      // Generate the fixed zip as ArrayBuffer 
      const fixedFileData = await zip.generateAsync({ type: 'arraybuffer', compression: 'DEFLATE' }); 
      
      // Now base64-encode fixedFileData to send to your API 
      const base64 = btoa(String.fromCharCode.apply(null, new Uint8Array(fixedFileData))); 
     
      return base64; 
    } 
      
    // Usage in your getFileAsync callback: 
    // fixHeaderImages(result.value).then(base64 => { 
    //     // Call your REST API with the fixed base64 string 
    // }); 
    

    This code explicitly handles the logic where imageheaderX.png is renamed to imageX.png and ensures the XML relationship points to the correct relative path (../media/). 

    Hope this helps! 


    If the answer is helpful, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".    

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.  


  2. Rajat Bharadwaj 5 Reputation points
    2026-01-30T13:59:51.7+00:00

    Screenshot 2026-01-30 at 7.09.34 PM.png

    This is how is see header image when i open document using base64 (out from function using Office.context.document.getFileAsync with Office.FileType.Compressed).

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.