Angular + Spring Boot + JasperSoft:无法加载PDF文档

问题描述 投票:0回答:2

我目前正在与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'});

}

angular spring-boot pdf-generation jaspersoft-studio
2个回答
0
投票

尝试此一个

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

0
投票

好的,我设法使它起作用。除了更改生成报告的方法之外,我还使用了@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'})
    };
}));}
© www.soinside.com 2019 - 2024. All rights reserved.