2017-03-09 44 views
1

我已經創建了一個SOAP服務,該服務可以正確生成XLSX Excel文件並將其保存到託管服務的服務器上。使用javascript保存xslx文件中的SOAP響應

相關代碼在這裏(JAVA):

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; 
} 

我用下面的代碼消費這項服務:

(JavaScript)的

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 = 
'<?xml version="1.0" encoding="utf-8"?>' + 
'<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://model/">' + 
    '<env:Header/>' + 
    '<env:Body>' + 
     '<ns1:getFile>' + 
     '<arg0>' + document.getElementById('sname1').value + '<\/arg0>' + 
     '<arg1>' + document.getElementById('fname1').value + '<\/arg1>' + 
     '<\/ns1:getFile>' + 
    '<\/env:Body>' + 
'<\/env:Envelope>' 

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 < 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); 
} 
... 

的 「的saveAs」 函數定義爲「 FileSaver.js「可在此處獲得: https://github.com/eligrey/FileSaver.js/

SOAP調用功能正常並將一個字節數組返回給soap服務 - 但是,在瀏覽器端下載後,Excel無法打開該文件。

在Excel中打開由FileOutputStream正確保存的服務器端文件。

使用NotePad ++(或任何可讓您看到不可見字符的編輯器),我看到一些不可見字符已從結果文件中除去。

我猜測我正在使用的一個或多個函數只是無法處理值並將其去掉。有誰知道是否這是我在Javascript端使用的函數的情況,或者是否有更好的方法來處理這個返回請求,以便我可以正確地提示用戶下載結果SOAP返回值(字節數組)作爲文件?

回答

0

我想通了這一點幾天後:

更新代碼的工作原理:

(JAVA)

public byte[] getFile(@WebParam(name = "arg0") String schemaName, @WebParam(name = "arg1") String tableName) { 
    Table tableData = new Table(schemaName, tableName); 
    ArrayList<String> columns = tableData.getAllColumnNames(); 
    XSSFWorkbook workbook = new XSSFWorkbook(); 
    byte[] data; 

    //... Create Excel using Apache POI API Here ... 
    try { 
     FileOutputStream outputStream = new FileOutputStream("C:\\testPath\\test.xlsx"); 
     workbook.write(outputStream); 
     Path path = Paths.get("C:\\testPath\\test.xlsx"); 
     data = Files.readAllBytes(path); 

     return data; 
    } 
    catch (IOException e) { 
     e.printStackTrace(); 
    } 
    return "".getBytes(); 
} 

(JavaScript)的

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 contentType = 'vnd.ms-excel'; 
      var y = x.childNodes[0]; 
      var b64Data = y.nodeValue 
      var blob = b64toBlob(b64Data, contentType) 
      saveAs(blob, "text.xlsx"); 
     } 
    } 
} 

利用函數「 b64toBlob「,用於將base 64數據轉換爲blob: Creating a Blob from a base64 string in JavaScript

我注意到的主要區別是,新的b64toBlob函數使用了切片大小,然後在轉換後將每個切片推送到主陣列上。我不知道爲什麼一次完成整件事情最初並不奏效。