Spring boot Birt Report with Angular 2 client Generates Corrupt PDF File
Asked Answered
O

1

2

I am trying to configure birt report in a spring boot applications, the client is an angular 2 application, here is where I run the report:

@PostConstruct
public void startUp() {
    if(inputDir == null)
        throw new RuntimeException("Cannot start application since birt report input directory was not specified.");
    try {
        EngineConfig engineConfig = new EngineConfig();
        engineConfig.getAppContext().put("spring", this.context);
        RegistryProviderFactory.releaseDefault();
        Platform.startup(engineConfig);
        IReportEngineFactory reportEngineFactory = (IReportEngineFactory) Platform.createFactoryObject(IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY);
        birtReportEngine = reportEngineFactory.createReportEngine(engineConfig);
    } catch (BirtException e) {

    }

    reportOutputDirectory = env.getProperty("birt_temp_file_output_dir");
}

@Override
public ByteArrayOutputStream runReport(Report birtReport) {
    ByteArrayOutputStream byteArrayOutputStream;
    File rptDesignFile;

    try {
        rptDesignFile = getReportFromFilesystem(birtReport.getName());
    } catch (Exception e) {
        throw new RuntimeException("Could not find report");
    }

    Map<String, String> parsedParameters = parseParametersAsMap(birtReport.getParameters());

    byteArrayOutputStream = new ByteArrayOutputStream();
    try {
        IReportRunnable reportDesign = birtReportEngine.openReportDesign(rptDesignFile.getPath());
        IRunTask runTask = birtReportEngine.createRunTask(reportDesign);

        if (parsedParameters.size() > 0) {
            for (Map.Entry<String, String> entry : parsedParameters.entrySet()) {
                runTask.setParameterValue(entry.getKey(), entry.getValue());
            }
        }
        runTask.validateParameters();

        String rptdocument = reportOutputDirectory + File.separator
                + "generated" + File.separator
                + birtReport.getName() + ".rptdocument";
        runTask.run(rptdocument);

        IReportDocument reportDocument = birtReportEngine.openReportDocument(rptdocument);
        IRenderTask renderTask = birtReportEngine.createRenderTask(reportDocument);

        PDFRenderOption pdfRenderOption = new PDFRenderOption();
        pdfRenderOption.setOption(IPDFRenderOption.REPAGINATE_FOR_PDF, new Boolean(true));
        pdfRenderOption.setOption(IPDFRenderOption.PAGE_OVERFLOW, IPDFRenderOption.OUTPUT_TO_MULTIPLE_PAGES );
        pdfRenderOption.setOption(IPDFRenderOption.PDF_TEXT_WRAPPING , true);
        pdfRenderOption.setOption(IPDFRenderOption.PDF_HYPHENATION  , true);
        pdfRenderOption.setOutputFormat("pdf");
        pdfRenderOption.setOutputStream(byteArrayOutputStream);
        renderTask.setRenderOption(pdfRenderOption);

        renderTask.render();
        renderTask.close();

    } catch (EngineException e) {
        throw new RuntimeException();
    }

    return byteArrayOutputStream;
}

and this is the api service that returns the byte array:

@RequestMapping(value = "/birt", method = RequestMethod.POST)
public ResponseEntity<byte[]> getBIRTReport(@RequestBody ReportRequest reportRequest) {
    byte[] reportBytes;
    ResponseEntity<byte[]> responseEntity;
    try {
        reportBytes =
            new BIRTReport(
                reportRequest.getReportName(),
                reportRequest.getReportParameters(),
                reportRunner)
                .runReport().getReportContent().toByteArray();

        HttpHeaders httpHeaders = new HttpHeaders();

        httpHeaders.setContentType(MediaType.parseMediaType("application/pdf"));
        String fileName = reportRequest.getReportName() + ".pdf";
        httpHeaders.setContentDispositionFormData(fileName, fileName);
        httpHeaders.setCacheControl("must-revalidate, post-check=0, pre-check=0");
        responseEntity = new ResponseEntity<byte[]>(reportBytes, httpHeaders, HttpStatus.OK);
    } catch (Exception e) {
        responseEntity = new ResponseEntity<byte[]>(HttpStatus.NOT_IMPLEMENTED);
        return responseEntity;
    }
    return responseEntity;
}

and that is the angular 2 code:

 public getReport():Observable<any>{
    let params = {
        "reportName":"my report name",
        "reportParameters":"my params"
    };
    let headers = new Headers();
    headers.append('Content-Type','application/json');
    let options = new RequestOptions({headers: headers});
    return this.http.post("http://localhost:8080/reports/birt",JSON.stringify(params), options);
}

call the service:

getReport(){
this.reportService.getReport().subscribe(
  data => {
     var blob = new Blob([data._body], { type: 'application/pdf'})
         saveAs(blob, "myPdf.pdf");
         var fileUrl = URL.createObjectURL(blob);
         window.open(fileUrl);
  }
)

}

This method returns a corrupt file, can anyone figure out the problem?

Operetta answered 13/10, 2016 at 14:55 Comment(2)
Did you manage to solve this one? We're having a similar problem.Meggie
@PredragMaric the answer below have solved my problemOperetta
L
2

The problem is that you are missing responseType in options

let options = new RequestOptions({headers: headers, **responseType: ResponseContentType.Blob**});

After that you can just do

 window['saveAs'](response.blob(), 'filename.zip');
Localism answered 24/11, 2016 at 15:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.