我目前正在与Angular,Spring Boot和Jaspersoft进行项目合作,尝试预览从REST API中以字节数组形式检索的pdf文档时遇到问题。在新选项卡中打开链接时,我得到:无法加载PDF文档。该问题不应该与jrxml文件有关,因为我尝试了其他示例jrxml文件,但得到的结果相同。Failed to load pdf document screenshot
这里是代码:
@RequestMapping(value = "/daily-orders/{restaurantId}/export", method = RequestMethod.POST)
public ResponseEntity<?> exportDailyOrders(@PathVariable Long restaurantId) {
byte[] dailyOrdersBytes = exportService.exportDailyOrders(restaurantId);
HttpHeaders header = new HttpHeaders();
header.setContentDispositionFormData("inline", "dailyOrdersReport.pdf");
header.setContentType(MediaType.valueOf("application/pdf"));
header.setContentLength(dailyOrdersBytes.length);
return new ResponseEntity<Object>(dailyOrdersBytes, header, HttpStatus.OK);
}
以及用于生成pdf报告的代码。
@Override
public byte[] exportDailyOrders(Long restaurantId) {
SimpleOutputStreamExporterOutput exporterOutput = null;
byte[] bytes = new byte[0];
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
List<RestaurantDailyOrdersRowMapper> restaurantDailyOrders = orderDAO.getRestaurantDailyOrders(restaurantId);
File file = ResourceUtils.getFile("classpath:reports/daily-orders.jrxml");
JasperReport jasperReport = JasperCompileManager.compileReport(file.getAbsolutePath());
JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(restaurantDailyOrders);
Map<String, Object> parameters = new HashMap<>();
parameters.put("createdBy", "author");
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource);
JRXlsxExporter exporter = new JRXlsxExporter();
exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
exporterOutput = new SimpleOutputStreamExporterOutput(byteArrayOutputStream);
exporter.setExporterOutput(exporterOutput);
exporter.exportReport();
return byteArrayOutputStream.toByteArray();
} catch (JRException | IOException e) {
log.error("Unable to generate Report of type pdf.", e);
return bytes;
} finally {
if (exporterOutput != null) {
exporterOutput.close();
}
}
}
这里是Angular的代码:
exportDailyOrdersToPdf() {
this.exportService.generateDocumentReport(1).subscribe(response => {
let file = new Blob([response.data], { type: 'application/pdf' });
let fileURL = window.top.URL.createObjectURL(file);
window.top.open(fileURL, '_blank');
}, error => {
})
}
以及服务中的方法:
generateDocumentReport(restaurantId: number): Observable<any> {
return this.httpClient.post('https://localhost:8080/main/daily-orders/' + restaurantId + '/export', '',
{ responseType: 'arraybuffer'});
}
尝试此一个
Spring Controller
@RequestMapping(value = "/daily-orders/{restaurantId}/export", method = RequestMethod.POST)
public void exportDailyOrders(@PathVariable Long restaurantId, HttpServletResponse httpServletResponse) {
byte[] dailyOrdersBytes = exportService.exportDailyOrders(restaurantId);
ByteArrayOutputStream out = new ByteArrayOutputStream(dailyOrdersBytes.length);
out.write(dailyOrdersBytes, 0, dailyOrdersBytes.length);
httpServletResponse.setContentType("application/pdf");
httpServletResponse.addHeader("Content-Disposition", "inline; filename=dailyOrdersReport.pdf");
OutputStream os;
try {
os = httpServletResponse.getOutputStream();
byteArrayOutputStream.writeTo(os);
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
/*HttpHeaders header = new HttpHeaders();
header.setContentDispositionFormData("inline", "dailyOrdersReport.pdf");
header.setContentType(MediaType.valueOf("application/pdf"));
header.setContentLength(dailyOrdersBytes.length);
return new ResponseEntity<Object>(dailyOrdersBytes, header, HttpStatus.OK);*/
}
Angular Service
import { map } from "rxjs/operators";
generateDocumentReport(restaurantId: number): Observable<any> {
let headers = new HttpHeaders();
headers.append('Accept', 'application/pdf');
let requestOptions: any = { headers: headers, responseType: ResponseContentType.Blob };
return this.httpClient.post('https://localhost:8080/main/daily-orders/' + restaurantId + '/export', '',requestOptions).pipe(map((response)=>{
return {
filename: 'dailyOrdersReport.pdf',
data: response.blob()
};
}));
}
Angular Component
exportDailyOrdersToPdf() {
this.exportService.generateDocumentReport(1).subscribe(response => {
console.log(response);
var url = window.URL.createObjectURL(response.data);
var a = document.createElement('a');
document.body.appendChild(a);
a.setAttribute('style', 'display: none');
a.setAttribute('target', 'blank');
a.href = url;
a.download = response.filename;
a.click();
window.URL.revokeObjectURL(url);
a.remove();
}, error => {
console.log(error);
});
}
好的,我设法使它起作用。除了更改生成报告的方法之外,我还使用了@hrdkisback代码。如果有人遇到类似问题,这是完整的代码。
控制器:
@RequestMapping(value = "/daily-orders/{restaurantId}/export", method = RequestMethod.POST)
public void exportDailyOrders(@PathVariable Long restaurantId, HttpServletResponse httpServletResponse) throws IOException, JRException {
byte[] dailyOrdersBytes = exportService.exportDailyOrders(restaurantId);
ByteArrayOutputStream out = new ByteArrayOutputStream(dailyOrdersBytes.length);
out.write(dailyOrdersBytes, 0, dailyOrdersBytes.length);
httpServletResponse.setContentType("application/pdf");
httpServletResponse.addHeader("Content-Disposition", "inline; filename=dailyOrdersReport.pdf");
OutputStream os;
try {
os = httpServletResponse.getOutputStream();
out.writeTo(os);
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
服务:
@Override
public byte[] exportDailyOrders(Long restaurantId) throws IOException, JRException {
List<RestaurantDailyOrdersRowMapper> restaurantDailyOrders = orderDAO.getRestaurantDailyOrders(restaurantId);
File file = ResourceUtils.getFile("classpath:reports/daily-orders.jrxml");
JasperReport jasperReport = JasperCompileManager.compileReport(file.getAbsolutePath());
JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(restaurantDailyOrders);
Map<String, Object> parameters = new HashMap<>();
parameters.put("createdBy", "Nikola");
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource);
ByteArrayOutputStream byteArrayOutputStream = getByteArrayOutputStream(jasperPrint);
return byteArrayOutputStream.toByteArray();
}
protected ByteArrayOutputStream getByteArrayOutputStream(JasperPrint jasperPrint) throws JRException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
JasperExportManager.exportReportToPdfStream(jasperPrint, byteArrayOutputStream);
return byteArrayOutputStream;
}
component.ts
exportDailyOrdersToPdf() {
this.exportService.generateDocumentReport(1).subscribe(response => {
console.log(response);
let url = window.URL.createObjectURL(response.data);
let a = document.createElement('a');
document.body.appendChild(a);
a.setAttribute('style', 'display: none');
a.setAttribute('target', 'blank');
a.href = url;
a.download = response.filename;
a.click();
window.URL.revokeObjectURL(url);
a.remove();
}, error => {
console.log(error);
});}
service.ts
generateDocumentReport(restaurantId: number): Observable<any> {
let headers = new HttpHeaders();
headers.append('Accept', 'application/pdf');
let requestOptions: any = { headers: headers, responseType: 'blob' };
return this.httpClient.post('https://localhost:8080/main/daily-orders/' + restaurantId + '/export', '', requestOptions)
.pipe(map((response)=>{
return {
filename: 'dailyOrdersReport.pdf',
data: new Blob([response], {type: 'application/pdf'})
};
}));}