2017-06-24 94 views
0

我有一個Springboot休息控制器來下載文件。我試圖使用瀏覽器訪問端點,並能夠在xhr.response中查看響應。但是,我想強制文件下載,我無法實現。如何使用Springboot @RestController通過AJAX下載文件

的代碼如下: 基於REST的端點(Springboot):

@GetMapping(value = "download/{id}", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE, consumes = "*/*") 
public ResponseEntity<InputStreamResource> getFile(@PathVariable("id") Long contractId) { 

    Contract contract; 
    contract = this.contractRepository.findOne(contractId); 
    System.out.println(contract.getPath()); // test 
    InputStreamResource resource = null; 
    HttpHeaders   respHeaders = new HttpHeaders(); 

    if (contract != null) { 

     try { 
      File   file   = new File(contract.getPath()); 
      FileInputStream fileInputStream = new FileInputStream(file); 
      resource = new InputStreamResource(fileInputStream); 
      System.out.println(resource.exists());//test 

      respHeaders.add("Content-Type", URLConnection.guessContentTypeFromStream(fileInputStream)); 
      respHeaders.add("Cache-Control", "no-cache, no-store, must-revalidate"); 
      respHeaders.add("Pragma", "no-cache"); 
      respHeaders.add("Expires", "0"); 
      respHeaders.add("Content-Disposition", "attachment;filename=" + file.getName()); 
      respHeaders.add("Content-Transfer-Encoding", "Binary"); 
      respHeaders.setContentLength(file.length()); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    return new ResponseEntity<InputStreamResource>(
      this.companyService.downloadContract(contractId), 
      respHeaders, 
      HttpStatus.OK 
    ); 


} 

我XHR請求如下

var xhr = new XMLHttpRequest(); 
 
xhr.open("GET", http.getHRTargetURL() + "download/" + id, true); 
 
xhr.setRequestHeader("X-Auth-Token", http.getToken()); 
 
xhr.setRequestHeader("Accept", "application/octet-stream"); 
 
xhr.setRequestHeader("Content-Type", "application/octet-stream"); 
 
    
 
xhr.onreadystatechange = function() { 
 
    if (xhr.readyState == 4 && xhr.response != "0") { 
 
     console.log(xhr) 
 
     console.log("Downloaded file"); 
 
    } else { 
 
     console.log("error downloading document") 
 
    } 
 
    } 
 
xhr.send();

我能拿到來自端點的響應。我可以在瀏覽器中看到xhr響應中的文件內容 enter image description here

我的問題是如何強制在瀏覽器上彈出文件保存嚮導的響應。

回答

0

你可以嘗試這樣。

xhr.onreadystatechange = function() { 
    if (xhr.readyState == 4 && xhr.response != "0") { 
     console.log(xhr) 
     var windowUrl = window.URL || window.webkitURL; 
     var url = windowUrl.createObjectURL(xhr); 
     anchor.prop('href', url); 
     anchor.prop('download', "filename"); 
     anchor.get(0).click(); 
     windowUrl.revokeObjectURL(url); 
     console.log("Downloaded file"); 
    } else { 
     console.log("error downloading document") 
    } 
    } 
xhr.send(); 
+0

有一個錯字。您應該將windowUrl更改爲window.URL – Prakhar

+0

是否適合您?謝謝。我更新了我的答案。 –

0

好吧,我發現問題出在前端,而且與後端無關,因爲Springboot正在發送正確的響應。由迪內希提供上述我修改了我的答案回答

大廈如下

download(id, name){ 

    var xhr = new XMLHttpRequest(); 
    xhr.open("GET", http.getHRTargetURL() + "download/" + id, true); 
    xhr.setRequestHeader("X-Auth-Token", http.getToken()); 
    xhr.setRequestHeader("Content-Type", "application/octet-stream"); 
    xhr.responseType  = "blob"; 

    xhr.onreadystatechange = function() { 
     if (xhr.readyState == 4) { 
     var a = document.createElement("a"); 
     document.body.appendChild(a); 
     a.style = "display: none"; 
     var url = window.URL.createObjectURL(new Blob([xhr.response], {type: "octet/stream"})); 
     a.href  = url; 
     a.download = name; 
     a.click(); 
     window.URL.revokeObjectURL(url); 
     } else { 
     console.log("error downloading document") 
     } 
    } 
    xhr.send(); 

    } 
+0

'xhr.response'已經是一個blob。 – Musa