Home > Blockchain >  Save a PDF generated by SpringBoot in Angular
Save a PDF generated by SpringBoot in Angular

Time:12-05

I am trying to save a PDF using Angular and Spring Boot.

When I make an API call, my Java code is fetching the data from the database and transforming it to a byte-stream. This stream is sent as response.

if(format.equals(Constant.PDF_FORMAT)) {
    ByteArrayInputStream stream = reportPDF.generateReportDocument(dtos);
    HttpHeaders headers = new HttpHeaders();
    headers.add("Content-Disposition", "inline; filename=report.pdf");
    return ResponseEntity.ok()
                         .headers(headers)
                         .contentType(MediaType.APPLICATION_PDF)
                         .body(new InputStreamResource(stream));
}

I have to use this response and save the data into a PDF.

Component.ts

public getReports(type?: string): void {
    this.params['expected-format'] = type;

    if (type === 'json') {
      this.Service.getPilotReports(this.params).subscribe((res) => {
        this.reportsData = res;
        this.pilotBankSpinnerService.closeSpinner();
      });
    } else {
      this.Service.customGetForDownload(this.params).subscribe(
        (data: Blob) => {
          var file = new Blob([data], { type: 'application/pdf' });
          var fileURL = URL.createObjectURL(file);
          window.open(fileURL);
          var a = document.createElement('a');
          a.href = fileURL;
          a.target = '_blank';
          a.download = 'reports.pdf';
          document.body.appendChild(a);
          a.click();          
        },
        (error) => {
          console.log('getPDF error: ', error);
         
        }
      );
    }
}

Service.ts

public customGetForDownload<blob, T>(url: string, params: any): any {
    const headers = new HttpHeaders({ 'Content-Type': 'application/json', responseType: 'blob' });
    const httpParams = this.http.constructParams(params);
    const absoluteUrl = this.getAbsoluteUrl(url);
    return this.httpClient.get(absoluteUrl, {
      headers: headers,
      params: httpParams,
      responseType: 'blob' as 'json',
      observe: 'response',
    });
}

Though the file is getting saved. When I try to open the file, it says "Failed to load pdf document".

CodePudding user response:

Syntax Issues

First I see a syntax error:

  • missing argument in method-call: ByteArrayInputStream stream = reportPDF.generateReportDocument(dtos, ); (after the comma)

With this syntax error you most likely receive a compilation-error on console.

Assume this is a lapse and you can fix it to something like ByteArrayInputStream stream = reportPDF.generateReportDocument(dtos); then it should compile.

Boots without errors? Then test the endpoint!

Assume further your server application boots and runs without errors, then you could test the HTTP-endpoint with a HTTP-call.

You can test using a HTTP-client like CURL, postman or maybe even a browser.

Then you should receive a response with HTTP status code 200 and the body containing the PDF-file as binary with MIME-type application/pdf and specified header Content-Dispositon.

The browser is expected to prompt you with a download-dialogue.

Responding with a binary in Spring

Your InputStreamResource is a valid way, but you should be confident when using it.

In a Spring controller method, you can return the binary data in different types:

  • ResponseEntity<byte[]> as byte-array
  • ResponseEntity<ByteArrayOutputStream> as stream (not input-stream for reading input)
  • ResponseEntity<Resource> as abstract binary content, see Spring's Resource
  • ResponseEntity<File> as entire file

See also

There are also some response-directed ways especially in Spring:

  • return a InputStreamResource as you did
  • return a StreamingResponseBody is very convenient
  • write to a HttpServletResponse, probably the oldest way

See: How To Download A File Directly From URL In Spring Boot

From input to output

Remember: Input is for reading (e.g. from a request), output is for writing (e.g. to a response). So you need an output type, like byte[] or ByteArrayOutputStream etc for your response-body.

When reading input into ByteArrayInputStream stream you could copy from that input to an output-stream with e.g. Apache-Commons IOUtils: IOUtils.copy(in, out);. Or simply return the byte-array: byte[] data = stream.readAllBytes();

See: Java InputStream to Byte Array and ByteBuffer | Baeldung

  • Related