Reputation: 1221
I've an API which returns an Excel document as response. The request will be one simple JSON.
I've searched Google and found some code base to download the file and I've used it in my application, but I'm getting some errors and unable to find it out the solution. Below is my code base:
component.ts
import rxjs/Rx;
details = {id: 75,name: "some name"}
this.nameService.getData(this.details).subscribe(response => {
this.downloadFile(response);
})
downloadFile(data: Response) {
const blob = new Blob([data], { type: '.xlsx' });
const url= window.URL.createObjectURL(blob);
window.open(url);
}
nameService.ts
getData(postData) {
return this.httpService.post('https://localhost:8080/getFile/', postData);
}
httpService.ts
constructor(private http: HttpClient)
post(apiEndpoint: string, request: any) :Observable<any> {
return this.http.post<any>(apiEndpoint,request);
}
with the above code base I'm getting below two errors and the file is not downloaded.
"Type Response is not assignable to type Blobpart" in creating the Blob(const blob = new Blob([data], { type: '.xlsx' });)
(downloadFile(data: any))
the above error(1) will go but I'm getting an httperror
response as 'Syntax error: unexpected token P in json at position 0 at json.parse
Kindly help if anyone finds any solution to the above issues.
Upvotes: 20
Views: 90086
Reputation: 688
Set response-header { responseType: 'blob'}
in the request.
To download the excel, use the below function.
response - api response, fileName- excel name
downloadExcel(response, fileName) {
// Doing it this way allows you to name the file
var link = document.createElement('a');
link.href = window.URL.createObjectURL(response);
link.download = fileName;
link.click();
}
Upvotes: 6
Reputation: 1
If anyone wants only to download a file from assets, they can use this code:
<a href="./assets/files/file.xlsx" target="_blank"></a>
But you need to mention the location in angular.json
"architect": {
"build": {
"options": {
"assets": [
"src/assets/files"
]
}
}
}
Upvotes: 0
Reputation: 167
You need to Add { responseType : 'application/octet-stream'} in your get request as No need to call post method
{ responseType : 'application/octet-stream'}
And in .ts file
DownLoadExcel(){
this.MprService.downLoadRFQInfoExcel(this.revisionId).subscribe(data =>{this.downloadFile(data)});
}
downloadFile(data: Blob) {
const contentType = 'application/vnd.openxmlformats-ficedocument.spreadsheetml.sheet';
const blob = new Blob([data], { type: contentType });
const url = window.URL.createObjectURL(blob);
window.open(url);
}
Upvotes: 1
Reputation: 1345
While using { responseType: 'blob'}
as said by most answers here works, I'd suggest using responseType: 'arraybuffer'
instead of blob
with observe: 'response'
. Your call would then look like this:
this.httpClient.get(resource, {
headers: this.httpHeaders, // Any custom client side headers like Authorization
observe: 'response',
responseType: 'arraybuffer'
});
The advantage of this is two-fold:
blob
or an arraybuffer
, using the Content-Type
observe: 'response'
will also include the response headers that you set at the server in the parsed response.I use this method to put the filename and the MIME Type of the arraybuffer
in the Content-Disposition
and Content-Type
response headers and then use a generic download service at the client-side.
Also, I would suggest using a File
object instead of just the Blob
, which gives you the flexibility of giving it a filename like so:
public downloadFile(response: any, fileName?: string) {
const blob = new Blob([response.body], { type: response.headers.get('content-type') });
fileName = fileName || response.headers.get('content-disposition').split(';')[0];
const file = new File([blob], fileName, { type: response.headers.get('content-type') });
saveAs(file);
}
This will also solve the problem that @knbibin raised about using a custom filename.
Upvotes: 11
Reputation: 101
To download the file use the below code
downloadFile(data: Response) {
const blob = new Blob([data], { type: 'application/octet-stream' });
fs.saveAs(blob, fileName + '.xlsx');
}
Upvotes: 2
Reputation: 1591
You need to set the response-header { responseType: 'blob'}
in the request.
You need to pass in the correct MIME-Type as you'are creating the blob-file. (f.e. application/octet-stream or application/vnd.openxmlformats-officedocument.spreadsheetml.sheet).
component.ts
downloadFile(data: Response) {
const blob = new Blob([data], { type: 'application/octet-stream' });
const url= window.URL.createObjectURL(blob);
window.open(url);
}
Upvotes: 17
Reputation: 22203
Add header { responseType: 'blob'}
Like this:
this.http.post<any>(apiEndpoint,request,{ responseType: 'blob'} )
Upvotes: 13