Hur man laddar ner en Excel-fil i Angular 8 som ett API-svar
Jag har en API som returnerar ett Excel-dokument som svar. Förfrågan kommer att vara ett enkelt JSON.
Jag har sökt på Google och hittat någon kodbas för att ladda ner filen och jag har använt den i min applikation, men jag får några fel och kan inte hitta lösningen. Nedan är min kodbas:
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);
}
Med ovanstående kodbas får jag nedanstående två fel och filen laddas inte ner.
- Får felet:
"Typen Response kan inte tilldelas typen Blobpart" vid skapande av Blob (const blob=new Blob([data], { type: '.xlsx' });)
- Om jag ändrar datan till vilken
(downloadFile(data: any))som helst försvinner ovanstående fel(1) men jag får etthttperror-svar som 'Syntaxfel: oväntad token P i JSON på position 0 vidjson.parse'
Var vänlig hjälp om någon hittar någon lösning på ovanstående problem.
Svar #1
Du behöver ange svarshuvudet
{ responseType: 'blob'}i förfrågan.Du behöver ange rätt MIME-typ när du skapar blob-filen. (t.ex. application/octet-stream eller application/vnd.openxmlformats-officedocument.spreadsheetml.sheet).
komponent.ts
downloadFile(data: Response) {
const blob = new Blob([data], { type: 'application/octet-stream' });
const url= window.URL.createObjectURL(blob);
window.open(url);
}
Svar #2
Lägg till header { responseType: 'blob'}
Så här:
this.http.post<any>(apiEndpoint,request,{ responseType: 'blob'} )
Svar #3
Även om användning av { responseType: 'blob'} som de flesta svar här säger fungerar, skulle jag föreslå att använda responseType: 'arraybuffer' istället för blob med observe: 'response'. Ditt anrop skulle då se ut så här:
this.httpClient.get(resource, {
headers: this.httpHeaders, // Any custom client side headers like Authorization
observe: 'response',
responseType: 'arraybuffer'
});
Fördelen med detta är tvåfaldig:
- Arraybuffer är ett generiskt flöde av bytes och Blob-objektet kan skapas med antingen en
blobeller enarraybuffer, med hjälp avContent-Type observe: 'response'kommer också att inkludera svarshuvuden som du har ställt in på servern i det analyserade svaret.
Jag använder denna metod för att lägga filnamnet och MIME-typen för arraybuffer i Content-Disposition och Content-Type svarshuvuden och sedan använda en generell nedladdningstjänst på klientsidan.
Jag skulle också föreslå att använda ett File-objekt istället för bara Blob, vilket ger dig flexibiliteten att ge det ett filnamn på följande sätt:
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);
}
Detta kommer också att lösa problemet som @knbibin tog upp om att använda ett eget filnamn.
