调用从Angular 6下载pdf的Spring启动api给出错误无法解析响应

Ahm*_*ssy 3 javascript typescript angular angular-httpclient

我有一个创建pdf报告并下载它的spring boot API,如果我直接在浏览器中调用API,则直接创建和下载pdf,但是当我从Angular 6调用GET API时,我收到以下错误:

Spring启动(java)代码:

@RequestMapping(value = "/app_report/en", method = RequestMethod.GET)
@ResponseBody
public void getEnRpt(HttpServletResponse response, @RequestParam("appNum") String appNum) throws JRException, IOException, SQLException {

    JasperReport jasperReport = JasperCompileManager.compileReport("./src/main/resources/jasperReports/App_created_en.jrxml");

    Connection connection = dataSource.getConnection();

    Map<String, Object> params = new HashMap<>();
    params.put("P_APP_NO", appNum);
    JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, params, connection);

    response.setContentType("application/x-pdf");
    response.setHeader("Content-disposition", "inline; filename=App_report_en.pdf");

    final OutputStream outStream = response.getOutputStream();
    JasperExportManager.exportReportToPdfStream(jasperPrint, outStream);
}
Run Code Online (Sandbox Code Playgroud)

调用API的Angular代码:(我试过多种方式,这里显示了两个):

this.http.get(this.api_url + reportUrl, {
  responseType: 'blob'
}, ).subscribe((response: File) => {
  console.log('report is downloaded');
});

this.http.get(this.api_url + reportUrl).subscribe(
  (response) => {
    console.log('report is downloaded');
  });
Run Code Online (Sandbox Code Playgroud)

Angular调用API后得到的控制台错误:

error:
SyntaxError: Unexpected token % in JSON at position 0 at JSON.parse (<anonymous>) at XMLHttpRequest.onLoad 
message: "Http failure during parsing for https://localhost:7001/reports/app_report/en?appNum=xxxxxxx"
?
name: "HttpErrorResponse"
?
ok: false
?
status: 200
?
statusText: "OK"
?
url: "https://localhost:7001/reports/app_report/en?appNum=xxxxxx"
Run Code Online (Sandbox Code Playgroud)

我只需要像浏览器中发生的调用一样调用API,以便立即下载pdf

响应标头如下:

Content-disposition 
inline; filename=App_report_en.pdf
Content-Type    
application/x-pdf
Run Code Online (Sandbox Code Playgroud)

为什么Angular没有下载文件,就像我调用该API一样在浏览器中发生的事情?(特别是因为请求成功)

Dav*_*vid 8

为了避免JSON解析问题,您需要告诉http客户端响应将是一个blob,使用responseType: 'blob'请求选项.

然后,要实际让导航器打开文件,您可以按照此博客中的说明进行操作

    const fileName = "report.pdf";
    this.http.get(this.api_url + reportUrl, {  responseType: 'blob'})
    .subscribe((blob: Blob) => {
    console.log('report is downloaded');

    if (navigator.msSaveBlob) 
    { 
        // IE 10+
        navigator.msSaveBlob(blob, filename);
    }
    else 
    {
        let link = document.createElement("a");
        if (link.download !== undefined) 
        {
            let url = URL.createObjectURL(blob);
            link.setAttribute("href", url);
            link.setAttribute("download", fileName);
            link.style.visibility = 'hidden';
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        }
        else
        {
            //html5 download not supported
        }
    }   
});
Run Code Online (Sandbox Code Playgroud)

除了iOs之外,这应该适用于IE 10+和其他现代浏览器(参见CanIuse)