35

I'm trying to provide a pdf download from within an angular 2 app...

this code works:

    var reportPost = 'variable=lsdkjf';

    var xhr = new XMLHttpRequest();

    xhr.open("POST", "http://localhost/a2/pdf.php", true);
    xhr.responseType = 'blob';
    xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

    xhr.onreadystatechange = function() {//Call a function when the state changes.
        if(xhr.readyState == 4 && xhr.status == 200) {
            var blob = new Blob([this.response], {type: 'application/pdf'});
            saveAs(blob, "Report.pdf");
        }
    }

    xhr.send(reportPost);

but i would have liked to use angular 2's built-in Http client.

a little research:

and some test code:

    var headers = new Headers();
    headers.append('Content-Type', 'application/x-www-form-urlencoded');

    this.http.post('http://localhost/a2/pdf.php', reportPost,  {
        headers: headers
        })
        .retry(3)
        // .map( (res:any) => res.blob() ) // errors out
        .subscribe(
          (dataReceived:any) => {
            var blob = new Blob([dataReceived._body], {type: 'application/pdf'});
            saveAs(blob, "Report.pdf");
          },
          (err:any) => this.logError(err),
          () => console.log('Complete')
        );

ps. the saveAs function comes from here: https://github.com/eligrey/FileSaver.js

3
  • 1
    Seems like the blob()-method isn't implemented yet. See github.com/angular/angular/blob/master/modules/angular2/src/…. An issue tracking the implementation status can be found here: github.com/angular/angular/issues/2803 Commented Dec 8, 2015 at 21:38
  • How in the world did you get "saveAs" to work? I've installed the module, installed the typings, and still get "no such function: saveAs" when I run it.. sooooo annoying... how do you include it in the typescript code? (i use webpack, still haven't figured it out) Commented Mar 29, 2016 at 14:21
  • 1
    i've just been ignoring the error from the TS compiler. it still compiles... sloppy huh? Commented Mar 30, 2016 at 1:26

3 Answers 3

60

With the release of Angular2 final we can define for example a service:

@Injectable()
export class AngularService {

    constructor(private http: Http) {}

    download(model: MyModel) { //get file from service
        this.http.post("http://localhost/a2/pdf.php", JSON.stringify(model), {
            method: RequestMethod.Post,
            responseType: ResponseContentType.Blob,
            headers: new Headers({'Content-Type', 'application/x-www-form-urlencoded'})
        }).subscribe(
            response => { // download file
                var blob = new Blob([response.blob()], {type: 'application/pdf'});
                var filename = 'file.pdf';
                saveAs(blob, filename);
            },
            error => {
                console.error(`Error: ${error.message}`);
            }
        );
    }
}

This service will get the file and then serve it to a user.

Example for zip file: How to use JAX-RS and Angular 2+ to download a zip file

Sign up to request clarification or add additional context in comments.

5 Comments

thanks ! i missed the responseType: ResponseContentType.Blob.
can someone mark this as the correct answer please, I've been looking for this in ages.
import {ResponseContentType } from '@angular/http';
I had to use http.get(url, <any>{responseType: "application/octet-stream"}), because http.get did not recognize responseType of type ResponseContentType, and requires string. And you can't set other string than "json" so I had to fool TS compiler.
I get this error [ts] Property 'blob' does not exist on type 'Blob'. anyone knows why?
17

With @4.3, @5 and HttpClientModule, I ended up doing:

this.http.post(`${environment.server}/my/download`,
                data, 
                {responseType: 'blob', observe: 'response'})
              .map( res => ({content: res.body, 
                             fileName: res.headers.get('content-filename')}));

Comments

2

See here: https://stackoverflow.com/a/45666313/4420532

return this._http.get('/api/images/' + _id, {responseType: 'blob'}).map(blob => {
  var urlCreator = window.URL;
  return this._sanitizer.bypassSecurityTrustUrl(urlCreator.createObjectURL(blob));
})

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.