19
votes

I have problem very similar to this PDF Blob - Pop up window not showing content, but I am using Angular 2. The response on question was to set responseType to arrayBuffer, but it not works in Angular 2, the error is the reponseType does not exist in type RequestOptionsArgs. I also tried to extend it by BrowserXhr, but still not work (https://github.com/angular/http/issues/83).

My code is:

createPDF(customerServiceId: string) {
   console.log("Sending GET on " + this.getPDFUrl + "/" + customerServiceId);

   this._http.get(this.getPDFUrl + '/' + customerServiceId).subscribe(
       (data) => {
            this.handleResponse(data);
         });
}

And the handleResponse method:

handleResponse(data: any) {
     console.log("[Receipt service] GET PDF byte array " + JSON.stringify(data));

     var file = new Blob([data._body], { type: 'application/pdf' });            
     var fileURL = URL.createObjectURL(file);
     window.open(fileURL);
 }

I also tried to saveAs method from FileSaver.js, but it is the same problem, pdf opens, but the content is not displayed. Thanks

5

5 Answers

67
votes

I had a lot of problems with downloading and showing content of PDF, I probably wasted a day or two to fix it, so I'll post working example of how to successfully download PDF or open it in new tab:

myService.ts

downloadPDF(): any {
        return this._http.get(url, { responseType: ResponseContentType.Blob }).map(
        (res) => {
            return new Blob([res.blob()], { type: 'application/pdf' })
        }
}

myComponent.ts

this.myService.downloadPDF().subscribe(
        (res) => {
            saveAs(res, "myPDF.pdf"); //if you want to save it - you need file-saver for this : https://www.npmjs.com/package/file-saver

        var fileURL = URL.createObjectURL(res);
        window.open(fileURL); / if you want to open it in new tab

        }
    );

NOTE

It is also worth mentioning that if you are extending Http class to add headers to all your requests or something like that, it can also create problems for downloading PDF because you will override RequestOptions, which is where we add responseType: ResponseContentType.Blob and this will get you The request body isn't either a blob or an array buffer error.

4
votes

ANGULAR 5

I had the same problem which I lost few days on that.

Here my answer may help others, which helped to render pdf.

For me even though if i mention as responseType : 'arraybuffer', it was unable to take it.

For that you need to mention as responseType : 'arraybuffer' as 'json'.(Reference)

Working code

downloadPDF(): any {
    return this._http.get(url, {  responseType: 'blob' as 'json' }).subscribe((res) => {
        var file = new Blob([res], { type: 'application/pdf' });            
        var fileURL = URL.createObjectURL(file);
        window.open(fileURL);
    }
}

Referred from the below link

https://github.com/angular/angular/issues/18586

0
votes

Amit, You can rename the filename by adding a variable to the end of the string so saveAs(res, "myPDF.pdf");

Becomes

saveAs(res, "myPDF_"+someVariable+".pdf");

where someVariable might be a counter or my personal favorite a date time string.

0
votes

This worked for me

 var req = this.getPreviewPDFRequest(fd);
        this.postData(environment.previewPDFRFR, req).then(res => {
          res.blob().then(blob => {
            console.clear();
            console.log(req);
            console.log(JSON.stringify(req));
            const fileURL = URL.createObjectURL(blob);
            window.open(fileURL, '', 'height=650,width=840');
          })
        });
0
votes

Server side (Java/Jetty) : REST service that returns a File Response The File Response itself will automatically be parsed into a pdf blob file by Jetty (because of the annotation @Produces("application/pdf") ), in other to be send to and read by the web client

    @GET
    @Path("/download-pdf/{id}")
    @Produces("application/pdf")
    public Response downloadPDF(@ApiParam(value = "Id of the report record")
                            @PathParam("id") Long id) {
        ResponseBuilder response = null;
        try {
            PDFReportService service = new PDFReportService();
            File reportFile = service.getPDFReportFile(id);

            response = Response.ok((Object) reportFile);  
            response.header("Content-Disposition","attachment; filename="+reportFile.getName());  
            return response.build();
        } catch (DomainException e) {
            response = Response.serverError().entity("server.error");
        }
        return response.build();
    }

Client side code (angular 2) : grab the blob and print it in a new browser tab

The key is to insure that you read the request reponse as a blob (as the server returned a blob; in my case)

Now, I tried so hard but I finally figured out that Angular 2 has not implemented any function to handle blob responses (neither res['_body'], nor res.blob() worked for me)

So I found no other workaround than using JQuery ajax to perform that file blob request, like following:

public downloadPDFFile() {
    let fileURL = serverURL+"/download-pdf/"+id;
    let userToken: string = your_token;

    showWaitingLoader();

    $.ajax({
        url: fileURL,
        cache: false,
        headers: {
            "Content-Type": "application/json",
            "Authorization": "Basic " + userToken
        },
        xhrFields: {
            responseType: 'blob' //Most important : configure the response type as a blob
        },
        success: function(blobFile) {
            const url = window.URL.createObjectURL(blobFile);
            window.open(url);
            stopWaitingLoader();
        },
        error: function(e){
            console.log("DOWNLOAD ERROR :", e);
        }
    });
}