问题描述
我有一个 spring boot API 可以创建 pdf 报告并下载它,如果我直接在浏览器中调用该 API,则会直接创建和下载 pdf,但是当我从 Angular 6 调用该 GET API 时,我得到以下内容错误:
I have a spring boot API that creates a pdf report and download it, if I call the API directly in the browser, the pdf is created and downloaded directly, but when I call that GET API from Angular 6 I get the following error:
Spring boot (java) 代码:
The Spring boot (java) code:
@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);
}
调用API的Angular代码:(我尝试了多种方式,这里展示了两种):
The Angular code that calls the API:( I tried multiple ways, two are shown here):
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');
});
Angular 调用 API 后出现的控制台错误:
The console error that I get after the Angular calls the 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"
我只需要像在浏览器中发生的调用一样调用API,以便立即下载pdf
I only need to call the API like the call that happens in the browser so that the pdf is downloaded right away
响应头如下:
Content-disposition
inline; filename=App_report_en.pdf
Content-Type
application/x-pdf
如果我调用该 API,为什么 Angular 不会像在浏览器中发生的情况那样下载文件?(特别是因为请求成功)
Why Angular is not downloading the file like what happens in the browser if I call that API? (especially since the request is successful)
推荐答案
为了避免 JSON 解析问题,您需要告诉 http 客户端响应将是一个 blob,使用 responseType: 'blob'代码>在请求选项中.
To avoid the JSON parsing issue, you need to tell the http client that the response will be a blob, using responseType: 'blob'
in requests options.
然后,要实际让导航器打开文件,您可以按照 这个博客
Then, to actually have the navigator open the file, you can follow the instructions from this blog
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
}
}
});
这应该适用于 IE 10+ 和其他现代浏览器,除了 iO(参见 CanIuse)
This should work for IE 10+ and other modern browsers, apart from iOs (see CanIuse)
这篇关于调用从 Angular 6 下载 pdf 的 Spring boot api 给出错误无法解析响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!