Angular 2 download PDF from API and Display it in View

In fact, this feature isn’t implemented yet in the HTTP support.

As a workaround, you need to extend the BrowserXhr class of Angular2 as described below to set the responseType to blob on the underlying xhr object:

import {Injectable} from 'angular2/core';
import {BrowserXhr} from 'angular2/http';

@Injectable()
export class CustomBrowserXhr extends BrowserXhr {
  constructor() {}
  build(): any {
    let xhr = super.build();
    xhr.responseType = "blob";
    return <any>(xhr);
  }
}

Then you need to wrap the response payload into a Blob object and use the FileSaver library to open the download dialog:

downloadFile() {
  this.http.get(
    'https://mapapi.apispark.net/v1/images/Granizo.pdf').subscribe(
      (response) => {
        var mediaType="application/pdf";
        var blob = new Blob([response._body], {type: mediaType});
        var filename="test.pdf";
        saveAs(blob, filename);
      });
}

The FileSaver library must be included into your HTML file:

<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2014-11-29/FileSaver.min.js"></script>

See this plunkr: http://plnkr.co/edit/tfpS9k2YOO1bMgXBky5Y?p=preview

Unfortunately this will set the responseType for all AJAX requests. To be able to set the value of this property, there are more updates to do in the XHRConnection and Http classes.

As references see these links:

Edit

After thinking a bit more, I think that you could leverage hierarchical injectors and configure this provider only at the level of the component that executes the download:

@Component({
  selector: 'download',
  template: '<div (click)="downloadFile() ">Download</div>'
  , providers: [
    provide(CustomBrowserXhr, 
      { useClass: CustomBrowserXhr }
  ]
})
export class DownloadComponent {
  @Input()
  filename:string;

  constructor(private http:Http) {
  }

  downloadFile() {
    this.http.get(
      'https://mapapi.apispark.net/v1/images/'+this.filename).subscribe(
        (response) => {
          var mediaType="application/pdf";
          var blob = new Blob([response._body], {type: mediaType});
          var filename="test.pdf";
          saveAs(blob, filename);
        });
    }
}

This override would only applies for this component (don’t forget to remove the corresponding provide when bootstrapping your application). The download component could be used like that:

@Component({
  selector: 'somecomponent',
  template: `
    <download filename="'Granizo.pdf'"></download>
  `
  , directives: [ DownloadComponent ]
})

Leave a Comment