How to download excel/Zip files in Angular 4
Try this:
downloadExcel() {
const type = 'application/vnd.ms-excel';
const filename = 'file.xls';
const options = new RequestOptions({
responseType: ResponseContentType.Blob,
headers: new Headers({ 'Accept': type })
});
this.http.get('http://10.2.2.109/Download/exportExcel', options)
.catch(errorResponse => Observable.throw(errorResponse.json()))
.map((response) => {
if (response instanceof Response) {
return response.blob();
}
return response;
})
.subscribe(data => saveAs(data, filename),
error => console.log(error)); // implement your error handling here
}
The key points are responseType: ResponseContentType.Blob
on the RequestOptions and response.blob()
when getting back the response.
In general, it's not recommended to access the _body
property of the response like this: response._body
, but instead you should call the relevant method to get the body content based on its type (like response.blob()
, response.json()
, etc)
Binish Prabhakar
Senior Software Engineer, passionate about JavaScript and all things Web, also full stalk development.
Updated on June 05, 2022Comments
-
Binish Prabhakar almost 2 years
I am using angular 4 as frond end and lumen 5.4 as back end.
My requirement is to export some data as excel and zip file.
Using import
{ saveAs }
from'file-saver/FileSaver';
package for file download.Angular 4 Code:
downloadExcel() { const type = 'application/vnd.ms-excel'; const headers = { headers: new Headers({ 'Accept': type }) }; const filename = 'file.xls'; this.http.get('http://10.2.2.109/Download/exportExcel', headers) .toPromise() .then(response => this.saveToFileSystem(response, type, filename)); return false; } private saveToFileSystem(response, __type, filename) { const contentDispositionHeader: string = response.headers.get('Content-Disposition'); if (contentDispositionHeader !== null) { const parts: string[] = contentDispositionHeader.split(';'); //const filename = parts[1].split('=')[1]; const blob = new Blob([response._body], { type: __type }); saveAs(blob, filename); } else { alert('Cant download.....'); // handling download condition if content disposition is empty const blob = new Blob([response._body], { type: __type }); saveAs(blob, filename); } }
Lumen Code
public function exportExcel(Request $request) { $file = storage_path(); $file_name = 'book1.xls'; $headers = [ 'Content-type' => 'application/vnd.ms-excel', 'Content-Disposition' => 'attachment;filename="' . $file_name, 'X-Filename' => $file_name, 'Content-Transfer-Encoding' => 'binary', 'Content-Length' => filesize($file . '/' . $file_name), 'Cache-Control' => 'max-age=0', 'Cache-Control' => 'max-age=1', 'Expires' => 'Mon, 26 Jul 1997 05:00:00 GMT', 'Last-Modified' => gmdate('D, d M Y H:i:s') . ' GMT', 'Cache-Control' => 'cache, must-revalidate', 'Pragma' => 'public', 'Set-Cookie' => 'fileDownload=true; path=/', 'Access-Control-Expose-Headers' => 'Content-Length,Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma' ]; return response()->download($file . '/' . $file_name, $file_name, $headers); }
Issues
const contentDispositionHeader: string = response.headers.get('Content-Disposition');
seems always empty.- We cant open downloaded file, shows corrupted message.
- It working for text file download
Please help me to resolve this issue. OR specify any other working code//package for angular
-
Binish Prabhakar over 6 yearsThank you :) One more doubt, how to modify the service to access both json data and blob data. The condition is we are passing authorization headers along with the request, if authorization fails or unable to generate excel API will return json. In that condition how we can change service to access response type to handle blob as well as json data.
-
Andrei Matracaru over 6 yearsSee my updated code sample for a possible solution. I added a catch operator that would catch any HTTP error responses (so basically HTTP error codes > 400), and would then extract the json out of the response, creating a new Observable with that content. Then, in the map you would have to check if the input is an instance of Response to extract the blob (the happy case), or if not just pass the content on (the error case). Bear in mind this is not tested, so I am not sure it will work. However, at least it should give you some ideas I hope :)
-
Binish Prabhakar over 6 yearsExcept blob data all other conditions we are returning json data with status code 200. In this case how we can handle.
-
Andrei Matracaru over 6 yearsWell, you shouldn't :). You should use HTTP codes for error conditions, such as 401 for unauthorized or 400 for bad request. Otherwise, I don't really see how you could distinguish between a successful response and an error. I guess you could try in the map function response.blob() inside a try block, and then response.json() in a catch block...but it's pretty ugly tbh
-
Binish Prabhakar over 6 yearsAs I am new to angular please advise me, for the above mentioned scenario what is the genius method to wrote code.
-
Binish Prabhakar over 6 yearsHow to catch error messages. If the http status is not 200. Right now we are using catch and subscribe response that are not able to get the response body. Only getting error. Statustext
-
Sanjay Tiwari almost 5 yearsWorks! for me but i have change
responseType: 'blob'
, this works for me of both files.csv
&.xlsx
type files. Please find my code....return this.http.get(url, { headers: headers, responseType: 'blob', observe: 'response' });