title: Saving an xslx document from a soap response with javascript
body: <p>I have created a SOAP service that correctly makes an XLSX Excel file and saves it to the server that the service is hosted on.</p>
  
  <p>Relevant code here (Java):</p>
  
  <pre><code>public byte[] getFile(@WebParam(name = "arg0") String schemaName, @WebParam(name = "arg1") String tableName) {                
    FileOutputStream outputStream = new FileOutputStream("example.xlsx"); 
    workbook.write(outputStream);
    File myFile = new File("example.xlsx");
    byte[] bytesArray = new byte[(int) myFile.length()];
    FileInputStream fis = new FileInputStream(myFile);
    fis.read(bytesArray); 
    fis.close();
    return bytesArray;
  }
  </code></pre>
  
  <p>I consume this service using the following code:</p>
  
  <p>(Javascript)</p>
  
  <pre><code>function sendFileSoap() {
  var xmlhttp = new XMLHttpRequest();
  var responseMessage;
  var fullResponse;
  xmlhttp.open('POST', 'http://127.0.0.1:7101/Application3-Model-context-root/ExcelConverterPort', true);
  
  // build SOAP request
  var requestBody =
  '&lt;?xml version="1.0" encoding="utf-8"?&gt;' +
  '&lt;env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://model/"&gt;' +
     '&lt;env:Header/&gt;' +
     '&lt;env:Body&gt;' +
        '&lt;ns1:getFile&gt;' +
          '&lt;arg0&gt;' + document.getElementById('sname1').value + '&lt;\/arg0&gt;' +
          '&lt;arg1&gt;' + document.getElementById('fname1').value + '&lt;\/arg1&gt;' +
        '&lt;\/ns1:getFile&gt;' +
     '&lt;\/env:Body&gt;' +
  '&lt;\/env:Envelope&gt;'
  
  xmlhttp.onreadystatechange = function () {
      if (xmlhttp.readyState == 4) {
          if (xmlhttp.status == 200) {
              fullResponse = xmlhttp.responseText;
              alert(fullResponse);
              var xmlDoc = xmlhttp.responseXML;
              var x = xmlDoc.getElementsByTagName("return")[0];
  
              var y = x.childNodes[0];
             downloadFile(y.nodeValue)
          }
      }
  }
  
  xmlhttp.setRequestHeader('Content-Type', 'text/xml');
  alert(requestBody);
  xmlhttp.send(requestBody);
  
  return responseMessage;
  }
  function downloadFile(characters) {          
          // convert base64 string to byte array
          var byteCharacters = atob(characters);
          var byteNumbers = new Array(byteCharacters.length);
          for (var i = 0; i &lt; byteCharacters.length; i++) {
              byteNumbers[i] = byteCharacters.charCodeAt(i);
          }
          var byteArray = new Uint8Array(byteNumbers);
  
          // now that we have the byte array, construct the blob from it
          var blob1 = new Blob([byteCharacters], {type: "application/vnd.ms-excel"});
  
          var fileName1 = "table.xlsx";
          saveAs(blob1, fileName1); 
  } 
  ...
  </code></pre>
  
  <p>The "saveAs" function is defined by "FileSaver.js" available here: 
  <a href="https://github.com/eligrey/FileSaver.js/" rel="nofollow noreferrer">https://github.com/eligrey/FileSaver.js/</a></p>
  
  <p>The SOAP call is functioning correctly and returning a byte array to the soap service - however Excel is unable to open the file after the download on the browser side.</p>
  
  <p>The file that is saved server-side by the FileOutputStream properly opens in Excel.</p>
  
  <p>Using NotePad++ (or any editor that lets you see invisible characters), I see that some of the non-visible characters have been stripped from the resulting file.</p>
  
  <p>I am guessing one or more of the functions I'm using just can't handle values and strip them out.  Does anyone know if this is the case for the functions I used on the Javascript side or if there is a better way to handle this return request so that I can properly prompt the user to download the resulting soap return value (byte array) as a file?</p>