Pages

Wednesday, February 15, 2017

Download a PDF in Angular 2

If you need to download a PDF file (stream) from your web service, there are a couple of key things to do.

Make sure you use the responseType property of the RequestOptions object (I'm using TypeScript here). You need to set this property to ResponseContentType.Blob (an enum from @angular/http)

Code snippet


// Depending on what you are sending to the server
// and what the server is sending back
let headers = new Headers({ 
   'Content-Type': 'application/json', 
   'Accept', 'application/pdf'
});


let options = new RequestOptions({ headers: headers });
// Ensure you set the responseType to Blob.
options.responseType = ResponseContentType.Blob;


Then, we will use the new Blob object in HTML5 to handle the response. To do this, create a new Blob using the response.blob() function in your map() function.

this.http
   .post(url, body, options)
   .map(response) => {
      // Removed checking of valid response
      ...
      let fileBlob = response.blob();
      let blob = new Blob([fileBlob], { 
         type: 'application/pdf' // must match the Accept type
      });
      ...
   })

Finally, use the saveAs() function of HTML5 to create the file on the client. Due to browser support, it is best to use the FileSaver JavaScript library (npm install file-saver, npm install @types/file-saver)

Don't forget to import it

...
import * as FileSaver from 'file-saver'; 
...

Then just use it after you have created the Blob.

...
let filename = 'mypdf.pdf';
FileSaver.saveAs(blob, filename);
...

Done.

Wednesday, January 18, 2017

Using RxJS Observable to return a simple value

So, I have a DataService that is using Observables (kinda the new Promises) to get a bunch of things, then when they are all ready it will get all the values and deal with them.
So functions that use the RxJS .post().map() etc will return Observable fine but I just wanted to return 10. As in the number 10. I don't really care if its Observable per se but I do want to be able to consume the function in the DataService as a promise. So how to you return a number 10? Here goes:

getNumber(): Observable {
   var observable = Observable.create((observer: Observer) => {
      observer.next(10);
      observer.complete();
   });
   return observable;
}

It can then be consumed, along with other promise-style functions and dealt with like promise.all()

Observable.forkJoin([
   this.dataService.getNumber(),
   this.dataService.getSomethingElse()
]).subscribe(results => {
   this.number = results[0];
   this.somethingElse = results[1];
});

Using the subscribe is like using promise.all()

Feels a bit weird at first, but basically if you want to return a promise of a simple type, just create a function like the getNumber() function above.