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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.