0

I have two Office.js applications:

  1. Prototype written in pure javascript
  2. React application

I can successfully call an end-point in the pure javascript application that downloads an MSWord document. This file is whole, complete and un-corrupted.

However, virtually identical code in the React application, calling the same end-point, downloading the same MSWord document returns a slightly larger data length (42523 vs 40554), The data begins identically, then changes as follows:

Working snippet of the document data 80,75,3,4,20,0,6,0,8,0,0,0,33,0,70,117,100,65533,1,0,0,32,8,0,0,19,0,8,2,91,67,111,110,116,101,110,116,95,84,121,...

Corrupted snippet of the document data 80,75,3,4,20,0,6,0,8,0,0,0,33,0,70,117,100,63462,63411,1,0,0,32,8,0,0,19,0,8,2,91,67,111,110,116,101,110,116,95,...

In my (working) pure javascript application the code looks like this:

                        downloadPath = "https://myserver.com/seal-ws/v5/downloads/6bb4dfd7e0a528dc68f2069f9d5da5a732692f49";

                        var xhr = new XMLHttpRequest;
                        xhr.open("GET", downloadPath);
                        xhr.addEventListener("load", function () {
                            var ret = [];
                            var len = this.responseText.length;

                            let trace = '';
                            for (let i = 0; i < len; i += 1) {
                                trace += this.responseText.charCodeAt(i) + ",";
                            }
                            console.log(trace);
                            console.log(len);


                        }, false);

                        xhr.setRequestHeader("X-Session-Token", XSessionToken);
                        xhr.overrideMimeType("octet-stream; charset=x-user-defined;");
                        xhr.send(null);

In the React application the code that returns the corrupt file looks like this:

        const downloadPath = "https://myserver.com/seal-ws/v5/downloads/6bb4dfd7e0a528dc68f2069f9d5da5a732692f49";

        const xhr = new XMLHttpRequest;
        xhr.open("GET", downloadPath);

        xhr.addEventListener("load", function () {
            const ret = [];
            const len = this.responseText.length;

            let trace = '';
            for (let i = 0; i < len; i += 1) {
                trace = `${trace}${this.responseText.charCodeAt(i)},`
            }
            console.log(trace);
            console.log(len);


        }, false);

        xhr.setRequestHeader("X-Session-Token", XSessionToken);
        xhr.overrideMimeType("octet-stream; charset=x-user-defined;");
        xhr.send(null);

I've used fiddlr to inspect the outgoing requests from both applications, and both look well formed and identically to one another. I don't understand why the response is being corrupted in the React application with what looks like near identical code?

It's not a browser difference, as I've tested with IE on both applications. The only thing I can think of is that the prototype is using a different version of the javascript file for the XMLHttpRequest object.

Pure Javascript App:

C:\Program Files (x86)\Microsoft Visual Studio 14.0\JavaScript\References\domWeb.js

React app:

C:\Users\\AppData\Local\Programs\Microsoft VS Code\resources\app\extensions\node_modules\typescript\lib\lib.dom.d.ts

Any ideas?

The above is a simplified version of what I'm trying to achieve in-order to illustrate the slight corruption in the data between the two approaches. Ultimately I'm trying to achieve a MSWord document download followed by an open new instance command as the following code describes. As detailed above, the following code workings in the prototype pure javascript application, but has this slight corruption in the React app. The resulting document opens correctly from pure javascript and fails to open the corrupted version from the React app. I'm sure it's nothing to do with React as a framework, but I struggling to understand what differences there could be that would cause the resulting data to be mis-decoded in this way:

        const downloadPath = "https://myserver.com/seal-ws/v5/downloads/6bb4dfd7e0a528dc68f2069f9d5da5a732692f49";
        const xhr = new XMLHttpRequest;
        xhr.open("GET", downloadPath);

        /* eslint-disable no-bitwise */
        xhr.addEventListener("load", function () {
            const ret = [];
            const len = this.responseText.length;
            console.log('len');
            console.log(len);
            let trace = '';
            for (let i = 0; i < len; i += 1) {
                trace = `${trace}${this.responseText.charCodeAt(i)},`
            }
            console.log(trace);

            let byte;
            for (let i = 0; i < len; i += 1) {
                byte = (this.responseText.charCodeAt(i) & 0xFF) >>> 0;
                ret.push(String.fromCharCode(byte));
            }
            let data = ret.join('');
            data = btoa(data);
            console.log(data);

            Word.run(context => {
                const myNewDoc = context.application.createDocument(data);
                context.load(myNewDoc);
                return context.sync().then(() => {
                    context.sync();
                    myNewDoc.open();
                });
            });                 

        }, false);

        xhr.setRequestHeader("X-Session-Token", XSessionToken);
        xhr.overrideMimeType("octet-stream; charset=x-user-defined;");
        xhr.send(null);
Paul Brown
  • 71
  • 1
  • 6

1 Answers1

0

Since two snippets that generate different outputs have nothing to do with React, try to just copy paste it to have the identical snippet in both projects.

I guess, the problem is that you do this:

trace = `${trace}${this.responseText.charCodeAt(i)},`

Which duplicates trace value instead of just accumulating new characters' codes on each iteration.

Igor Bykov
  • 2,532
  • 3
  • 11
  • 19
  • Thanks for your reply. I added the trace variable to illustrate the issue for this ticket. I've updated the ticket to include the full use-case that I'm trying to achieve which doesn't use that trace. What I don't understand is how I have working code in one javascript app that doesn't translate into a React.js app. – Paul Brown Jan 07 '20 at 09:22
  • @PaulBrown I honestly cannot think of any other possible solution. React.js doesn't modify prototypes of common APIs and even if it would, it wouldn't matter since same HTTP request should always return same data since responding server neither knows nor cares how you generated the request. – Igor Bykov Jan 11 '20 at 15:17