Goodbye GetAllContentAsync, Hello getFileAsync!


Hello apps for Office developers! This is Juan Balmori, PM of the JavaScript API for Office (aka Office.js). On this my first blog post I want to share with you a more detailed follow up to one of the changes mentioned on Ricardo’s “Important Developer Changes” blog post a few days ago. The one regarding the GetAllContentAsync method substitution.

Impact:

Basically the document.getAllContentAsync method will be deprecated and replaced by the document.getFileAsync method who offers the same functionality in a more robust way.

The rest of this blog post describes in detail the reasons for the replacement, affected scenarios, and suggested solutions.

Why we did this change?

A change like this is always painful, but the benefit is great. The change was required for 2 reasons:

1. Limited functionality: document.getAllContentAsync had the limitation to get a file for only up to 4MB in size, and no pagination/chunking we supported, so we were delivering the file in ‘one shot’.

2. PowerPoint integration: The scenarios that we want to enable in PowerPoint on this release require the get file content feature and while 4 MB in size covers a very good portion of Word documents, it was not the case for PowerPoint presentations which generally are larger.

The document.getFileAsync method will allow getting a document of any size in slices or chunks.

Scenarios that require a fix

  1. How to change your existing code to use the new method? The following table summarizes the code changes that need to happen to support the new method. These code snippets with old and new syntaxes, output exactly the same:
    Before
    // Gets the document content in base64 // (using getAllContentAsync), works only in Word.
    function getFileContentTheOldWay() { var fileContent; Office.context.document.getAllContentAsync( "base64", function (result) { if (result.status == "succeeded") fileContent = result.value; }); }
    After
    // Gets the document content in base64 // (using getFileAsync), works in Word and PowerPoint.
    function getFileContentTheNewWay() { var fileContent; Office.context.document.getFileAsync( "compressed", function (result) { var myFile = result.value; myFile.getSliceAsync( 0, function (result) { if (result.status == "succeeded") fileContent = OSF.OUtil.encodeBase64( result.value.data ); }); }); }
  2. What versions of Office.js should you use? There is no version of Office.js that supports both methods. There will be 2 public locations on a content delivery network (CDN) for Office.js

      

Version of Office.js

Location

API support

Preview Location

https://az88874.vo.msecnd.net/api/1.0/office.js

(works with Office Preview release)

Supports getAllContentAsync only

RTM (and final)

Location

https://appsforoffice.microsoft.com/lib/1.0/hosted/office.js

(works with Office RTM release)

Supports getFileAsync only

Eventually all apps must point to the final CDN location, which will be required when you submit apps to the Office Store. As a result, a task pane app that uses getFileAsync should show a message to invite the user to upgrade to the RTM release of Office, when the app is activated in the Preview release Word 2013.

The following example shows how to use the RTM version of Office.js to write code that will run on both the Preview and RTM releases of Office 2013. In the RTM release, the code just gets the file as expected. In the Preview release though, it will show a message to the user, inviting him to upgrade to the RTM version.

Note: The following are 2 examples of getting the file as base64 and as plain text. You should adjust this code to adapt to the UI design of your app.

Getting the File as Base 64

function getFileAsBase64() { 
    Office.context.document.getFileAsync(
        "compressed", 
        {}, 
        function (result){ 
            if (result.status == Office.AsyncResultStatus.Succeeded) { 
                var myFile = result.value; myFile.getSliceAsync(
                    0, 
                    function (result) { 
                        // Calling getFileAsync succeeded, which means 
                        // the app is on the RTM release, so 
                        // show the file. 
                        document.getElementById("result").innerText = 
                            OSF.OUtil.encodeBase64(result.value.data); 
                    }); 
            } 
            else { 
                try { 
                    // The next instruction will throw an exception 
                    // if a File Object is not returned, which is the 
                    // case in the Preview release. 
                    var sliceCount= result.value.sliceCount; 
                } 
                catch (e) { 
                    // Internal errors can happen for a number of reasons. 
                    // We need to check that the property does not exist. 
                    if (e.name == "TypeError") { 
                        document.getElementById("result").innerText = 
                            "This method is not supported in the " + 
                            "Office 2013 Preview, please update your " +
                            "Office to the latest release."; 
                    } 
                    else 
                    { 
                        // Handle any other exceptions here. 
                    }
                }
            }
        });
}

Getting the File as Plain Text

function getFileAsText() { 
    Office.context.document.getFileAsync(
        "text", 
        {}, 
        function (result) { 
            if (result.status == Office.AsyncResultStatus.Succeeded) { 
                var myFile = result.value; myFile.getSliceAsync(
                    0, 
                    function (result) { 
                        // Calling getFileAync succeeded, which means 
                        // the app is on the RTM release, so 
                        // show the file!! 
                        document.getElementById("result").innerText = 
                            result.value.data; 
                    }
                ); 
            } 
            else { 
                try { 
                    // The next instruction will throw an exception 
                    // if a File Object is not returned, which is the case 
                    // in the Preview release. 
                    var sliceCount= result.value.sliceCount; 
                } 
                catch (e) { 
                    // Internal errors can happen for a number of reasons. 
                    // We need to check that the property does not exist. 
                    if (e.name == "TypeError") { 
                        document.getElementById("result").innerText = 
                            "This method is not supported in the " + 
                            "Office 2013 Preview, please update your " + 
                            "Office to the latest release."; 
                    } 
                    else { 
                        // Handle any other exceptions here. 
                    }
                }
            }
        });
}
Comments (3)

  1. tim says:

    Is it possible to share a website with the web and with Office Apps and then conditionally load office.js? If I load office.js (debug and hosted), it always triggers a GetContext unhandled exception. Ideally, it would be fantastic if there was something in the Request header or type that indicates that the Office App is calling, but so far I haven't been able to find anything.

  2. yes this is possible, The challenge here is to identify if the app is been loaded in the context of Office. One way of doing this for apps in the marketplace is to verify if there is an 'et' parameter on the querystring. This is the parameter holding the entitlement token from the marketplace and is added only when the page is loaded in the context of the Marketplace and Office. the idea is to load Office.js at runtime only if this parameter exists.

    hope this helps…

  3. I'm having a problem running the "Getting the File as Base 64" example:

    I get a Javascript error when i call

    OSF.OUtil.encodeBase64(result.value.data);

    Unhandled exception at line 11, column 5517 in appsforoffice.microsoft.com/…/office.js

    Object doesn't support property or method 'charCodeAt'

    The result.value.data is type of object with a length of 17151 and looks like this:

    [0] 80

    [1] 75

    [2] 3

    [3] 4

    [4] 20

    I'm using IE10 and Word 2013 (15.0.4517.1003) MSO (15.0.4517.1005) 64-Bit on Windows 8.

    Any help would be greatly appreciated!