PDF Blob is not showing content, Angular 2
Asked Answered
R

5

19

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

Renaud answered 5/5, 2016 at 8:42 Comment(0)
S
67

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.

Stealing answered 23/9, 2016 at 9:37 Comment(14)
when I open pdf file with window.open(url) its stuck with popup blocker by the browser. Also can we also rename the file. any solution.Barrie
@PeterAlbert You're very welcome! To be honest, I didn't think anyone else would stumble upon the same problem. :)Stealing
I have the exact same problem: Because I set a "Range" header, the "responseType: ResponseContentType.Blob" seems to be ignored and "The request body isn't either a blob or an array buffer" is thrown (why request and not response??). Do you know how to avoid this?Hemicellulose
@RicoSuter If you are setting "Range" header after you set responseType, your responseType will be overwritten. You can set both simultaneously in order to avoid overwriting.Stealing
I use a plain object, so this shouldn't be a problem: let options_ = { body: content_, method: "get", responseType: ResponseContentType.Blob, headers: new Headers({ "Range": range, "Content-Type": "application/json; charset=UTF-8" }) }; return this.http.request(url_, options_);Hemicellulose
The res.blob() was what I was missing. Most examples I have seen just do [res]Contrariety
This worked for me perfectly, I was dealing with and image, not a pdfCopenhaver
I have a question about how to deal with the case when http is extended to add a JWT to every request. Are you willing to help? Here is the link.Fronia
@Fronia I am willing to try. :) You can create two methods for get requests in your CustomHttp, for example get() and getBlob() and you can use getBlob() for getting PDF and other files and regular get() for regular requests.Stealing
Legend, I was getting error "The request body isn't either a blob or an array buffer", this solution has resolved it all, thanks!Discontinuance
I'm not getting any result here. Drilling down in the returned blob, I see an exception: angular 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them at Function.remoteFunctionStile
This is actually downloading the pdf for me. The 'fileUrl' is actually "blob:localhost:50293/b8ec01fd-4cc2-4f4a-9001-594f8ae9441d"; without a .pdf extensionDodwell
I tried the same in angular 5 with observable subscribe, getting an error while rendering the pdf.Nigrescent
#63188258 can you help on this?Haruspicy
N
5

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

Nigrescent answered 24/5, 2018 at 19:12 Comment(0)
P
0

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.

Parisian answered 10/1, 2017 at 4:2 Comment(2)
Sorry about the Answer, I thought I was adding it as a comment to Amit's question.Parisian
#63188258 can you help on this?Haruspicy
D
0

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');
          })
        });
Dummy answered 26/5, 2021 at 21:41 Comment(0)
M
0

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);
        }
    });
}
Moil answered 31/5, 2021 at 19:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.