1

I have an Angular app that uses HttpClient for API calls. These return Observables of data types that I can use for various purposes, i.e. an Observable<Widget[]> can be used to display a list of Widget search results.

Now, I have just coded up a backend/API endpoint that generates an Excel spreadsheet of some search results the user would like to download in that file format. I don't need any code in my component to interpret or process that data, I just want to link the user to that URL when he clicks a link. I want to use HttpClient because the Angular app is configured with an "HTTP interceptor" that adds a bearer token as an HTTP header, authorizing the user to the backend/API. I don't want to code the same thing in two places.

So, the question simply is: how can I use HttpClient in Angular to simply link the user to a URL? (Probably I would do this in a "new tab" i.e. target='_blank' if that makes a difference to the answer.)

3 Answers 3

2

It's typical task: download files by link with auth bearer token. Simplest way to do it – download file as Blob and save it on client by a fake download link.

this.httpClient.get<Blob>('/api/.../xls').subscribe(blob => {
    const a = document.createElement('a');

    a.href = window.URL.createObjectURL(blob);
    a.download = 'Any file name with extension.xls';
    a.click();
    document.body.removeChild(a);
});
Sign up to request clarification or add additional context in comments.

2 Comments

I'm not sure what to do on the back end to produce a "Blob". My Java back-end writes an application/octet-stream to the HTTP response, and in Angular I'm getting an error that this is not valid JSON. The message body isn't JSON at all. Have you got an example of how a back-end would provide a valid "Blob"?
OK I guess the trick would be to produce a JSON in the "blob" format from the back end.
0

Interceptor does not work for router link navigations or navigations in general. You should navigate to page dedicated to this action of downloading the report like below.


You can create a dummy page, that you open in a new tab using _blank.

downloadExcelReport(){
    window.open(<<my url>>/excel-report, "_blank");
}

For this route, all you need to do is make the HttpCall to the backend.

ngOnInit() {
    this.http.get('backend url that fetches the excel report').subscribe()
}

The interceptor will do it's job of adding the auth token, so the request is made authorized and authenticated.

After this, your backend whichever language should perform the redirect to the download URL or viewer URL:

Can Node js redirect to a url and display it in another new browser?

Comments

0

I developed an answer based on ZloDeeV's answer. My back end doesn't export a "blob" in JSON, but rather returns the excel file directly as an application/octet-stream, so I had to modify the code a bit, removing the <Blob> generic and treating the download as an arraybuffer:

this.httpClient.get('/api/.../xls', {responseType:'arraybuffer'}).subscribe(response => {
    const a = document.createElement('a');
    let blob = new Blob([response], {type: "application/ms-excel"});
    a.href = window.URL.createObjectURL(blob);
    a.download = 'filename.xlsx';
    a.click();
    document.body.removeChild(a);
});

This works in my situation. I believe that the "type" might be incorrect and application/vnd.ms-excel might be preferred, but I haven't tested that and the above code works.

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.