Angular + Spring Boot + JasperSoft: не удалось загрузить PDF документ - PullRequest
0 голосов
/ 16 января 2020

В настоящее время я работаю над проектом с Angular, Spring Boot и Jaspersoft, и у меня возникают проблемы с предварительным просмотром документа PDF, полученного в виде массива байтов из REST API. Когда ссылка открывается в новой вкладке, я получаю: Не удалось загрузить документ PDF. Проблема не должна быть с файлом jr xml, потому что я пробовал с другими примерами файлов jr xml, и я получаю тот же результат. Не удалось загрузить скриншот документа pdf

Вот код:

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

}

Ответы [ 2 ]

0 голосов
/ 16 января 2020

Хорошо, мне удалось заставить его работать. Я использовал часть кода @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'})
    };
}));}
0 голосов
/ 16 января 2020

Попробуйте это

Пружинный контроллер

@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 Сервис

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 Компонент

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);
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...