I would like to change to the new HttpClient. Until now I handle file downloads the following:
getXlsx (): Observable<any> {
return this.http.get('api/xlsx', {
responseType: ResponseContentType.ArrayBuffer, // set as ArrayBuffer instead of Json
})
.map(res => downloadFile(res, 'application/xlsx', 'export.xlsx'))
.catch(err => handleError(err));
}
export function downloadFile(data: any, type: string, filename: string): string {
const blob = new Blob([data._body], { type });
const url = window.URL.createObjectURL(blob);
// create hidden dom element (so it works in all browsers)
const a = document.createElement('a');
a.setAttribute('style', 'display:none;');
document.body.appendChild(a);
// create file, attach to hidden element and open hidden element
a.href = url;
a.download = filename;
a.click();
return url;
}
Changing the respondeType to 'arraybuffer' will result in empty files. Any ideas how to solve it?
HTTP GET. The HttpClient.get sends the HTTP Get Request to the API endpoint and parses the returned result to the desired type. By default, the body of the response is parsed as JSON. If you want any other type, then you need to specify explicitly using the observe & responseType options. You can read more about Angular HTTP Get. Syntax
Using Angular HttpClient. The HttpClient is a separate model in Angular and is available under the @angular/common/http package. All you need to do is to import it and inject it into our component/service. Then, Use HttpClient.Get method to send an HTTP Request and Subscribe to the response Asynchronously.
Creating services with the help of angular cli is one of the best ways to do so. You can create one manually but its always easier to generate it using the CLI as it uses the latest syntax and creates the service, its spec and adds it to the nearest module as a provider.
Run the Angular application with help of angular-cli command ng serve, and you will get a message like, “Angular Live Development Server is listening on localhost:4200. Open your browser on http://localhost:4200/.” Once you open the URL in your browser, you will get an output like the image below.
So Martin has solved my issue:
getXlsx (): Observable<any> {
return this.http.get('api/xlsx', {
responseType: 'blob' // <-- changed to blob
})
.map(res => downloadFile(res, 'application/xlsx', 'export.xlsx'))
.catch(err => handleError(err));
}
export function downloadFile(blob: any, type: string, filename: string): string {
const url = window.URL.createObjectURL(blob); // <-- work with blob directly
// create hidden dom element (so it works in all browsers)
const a = document.createElement('a');
a.setAttribute('style', 'display:none;');
document.body.appendChild(a);
// create file, attach to hidden element and open hidden element
a.href = url;
a.download = filename;
a.click();
return url;
}
The above works and is an acceptable solution, however seems like a code smell just adding anchor tags to the DOM and faking a click when you can do it in a much cleaner way. We've recently had a similar issue for downloading documents in general from an Angular 5 website in which we have used FileSaver(https://www.npmjs.com/package/file-saver) .
Adding FileSaver using npm install file-saver
and doing the relevant imports you can use the following code to download a file:
getDocument(document: Document) {
let headers = new HttpHeaders(); // additional headers in here
return this._http.get(url, {
headers: headers,
responseType: "blob" // this line being the important part from the previous answer (thanks for that BTW Martin)
}).map(
res => {
var x = res;
if (res) {
let filename = documentName;
saveAs(x, filename);
}
return true;
},
err => {
return true;
}
);
}
This uses the native saveAs
command if it exists and implements some other logic to replicate the functionality if it doesn't.
This may do a similar thing under the hood (i don't really know as haven't had the change to look), but it compartmentalises it in an easy to use third party package that I would hope would be maintained (fingers crossed) without me having to update functionality to cater for newer versions of different packages / browsers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With