3

I have a REST API that if I query directly in the browser, it returns a JSON or CSV file to download. I want to do the same thing with the Angular HttpModule.

My get request is simple (it has a query string param to indicate which file format to return):

public Submit(request: Request) {
  ...
  return this.http.get(url).subscribe(response => {
    //What here
  });
}

The response content-type is application/octet-stream. I've tried processing the response as a blob, which doesn't work. How can I just pass through the response from the server to the browser and let it download the file? This method is part of a service that is being called by a component that is responding to a button click

onClick() {
    this._requestService.Submit(request); //This gets the Subscription response from the service, but I want it to let the broswer download the file
}
mhaken
  • 1,075
  • 4
  • 14
  • 28

3 Answers3

5

You have to add

{ responseType: ResponseContentType.Blob }

and then map response to blob.

return this.http.get(url, { responseType: ResponseContentType.Blob })
    .map(r => r.blob())
    .subscribe(response => {

    });

Next you can download this file using fileSaver.js.

4

you could try something like this:

this.http.get(url).subscribe(response => {
  const blob = new Blob([response], { type: 'text/csv' });
  const url= window.URL.createObjectURL(blob);
  window.open(url);
});
Dean Chalk
  • 20,076
  • 6
  • 59
  • 90
  • 1
    Tried that, I get an error: `Resource 'blob:6BB5A3D5-0D0D-4537-B4F3-888D7A70DE57' not allowed to load.` – mhaken Jul 29 '17 at 16:40
1

I got most of the solution from AngularJS $http-post - convert binary to excel file and download and AngularJS: Display blob (.pdf) in an angular app.

let ieEDGE = navigator.userAgent.match(/Edge/g);
let ie = navigator.userAgent.match(/.NET/g); // IE 11+
let oldIE = navigator.userAgent.match(/MSIE/g); 

let blob = new Blob([response.text()], { type: "application/octet-stream"});
let fileName: string = "myfile." + this.request.output;

if (ie || oldIE || ieEDGE) {
  window.navigator.msSaveBlob(blob, fileName);
}
else {
  let link = document.createElement('a');
  link.href = window.URL.createObjectURL(blob);
  link.download = fileName;
  link.click(); 

  setTimeout(function () {
    window.URL.revokeObjectURL(url);
  }, 0);
}

For non IE browsers (the "else" statement), I was also able to successfully use

let reader = new FileReader();
reader.onloadend = function () {
  window.location.href = reader.result;
};

reader.readAsDataURL(blob);

For the second approach, it's important that the blob type is application/octet-stream, otherwise for something like application/json or text/csv, it will open the file in a new window/tab. The downside is that you can't provide a file name or extension, so you get a raw file called "download".

mhaken
  • 1,075
  • 4
  • 14
  • 28