Converting byte array output into Blob corrupts file
I ended up doing this with the fileContent string:
let bytes = new Uint8Array(fileContent.length);
for (let i = 0; i < bytes.length; i++) {
bytes[i] = fileContent.charCodeAt(i);
}
I then proceed to build the Blob with these bytes:
let blob = new Blob([bytes], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
If I then send this via a POST request, the file isn't mangled and can be opened correctly by Word.
I still get the feeling this can be achieved with less hassle / less steps. If anyone has a better solution, I'd be very interested to learn.
Squrler
Updated on June 17, 2022Comments
-
Squrler almost 2 years
I am using the Office Javascript API to write an Add-in for Word using Angular.
I want to retrieve the Word document through the API, then convert it to a file and upload it via POST to a server.
The code I am using is nearly identical to the documentation code that Microsoft provides for this use case: https://dev.office.com/reference/add-ins/shared/document.getfileasync#example---get-a-document-in-office-open-xml-compressed-format
The server endpoint requires uploads to be POSTed through a multipart form, so I create a FormData object on which I append the file (a blob) as well as some metadata, when creating the $http call.
The file is being transmitted to the server, but when I open it, it has become corrupted and it can no longer be opened by Word.
According to the documentation, the Office.context.document.getFileAsync function returns a byte array. However, the resulting fileContent variable is a string. When I console.log this string it seems to be compressed data, like it should be.
My guess is I need to do some preprocessing before turning the string into a Blob. But which preprocessing? Base64 encoding through atob doesn't seem to be doing anything.
let sendFile = ( fileContent ) => { let blob = new Blob([fileContent], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' }), fd = new FormData(); blob.lastModifiedDate = new Date(); fd.append('file', blob, 'uploaded_file_test403.docx'); fd.append('case_id', caseIdReducer.data()); $http.post('/file/create', fd, { transformRequest: angular.identity, headers: { 'Content-Type': undefined } }) .success( ( ) => { console.log('upload succeeded'); }) .error(( ) => { console.log('upload failed'); }); }; function onGotAllSlices(docdataSlices) { let docdata = []; for (let i = 0; i < docdataSlices.length; i++) { docdata = docdata.concat(docdataSlices[i]); } let fileContent = new String(); for (let j = 0; j < docdata.length; j++) { fileContent += String.fromCharCode(docdata[j]); } // Now all the file content is stored in 'fileContent' variable, // you can do something with it, such as print, fax... sendFile(fileContent); } function getSliceAsync(file, nextSlice, sliceCount, gotAllSlices, docdataSlices, slicesReceived) { file.getSliceAsync(nextSlice, (sliceResult) => { if (sliceResult.status === 'succeeded') { if (!gotAllSlices) { // Failed to get all slices, no need to continue. return; } // Got one slice, store it in a temporary array. // (Or you can do something else, such as // send it to a third-party server.) docdataSlices[sliceResult.value.index] = sliceResult.value.data; if (++slicesReceived === sliceCount) { // All slices have been received. file.closeAsync(); onGotAllSlices(docdataSlices); } else { getSliceAsync(file, ++nextSlice, sliceCount, gotAllSlices, docdataSlices, slicesReceived); } } else { gotAllSlices = false; file.closeAsync(); console.log(`getSliceAsync Error: ${sliceResult.error.message}`); } }); } // User clicks button to start document retrieval from Word and uploading to server process ctrl.handleClick = ( ) => { Office.context.document.getFileAsync(Office.FileType.Compressed, { sliceSize: 65536 /*64 KB*/ }, (result) => { if (result.status === 'succeeded') { // If the getFileAsync call succeeded, then // result.value will return a valid File Object. let myFile = result.value, sliceCount = myFile.sliceCount, slicesReceived = 0, gotAllSlices = true, docdataSlices = []; // Get the file slices. getSliceAsync(myFile, 0, sliceCount, gotAllSlices, docdataSlices, slicesReceived); } else { console.log(`Error: ${result.error.message}`); } } ); };