I am trying to stream a csv
file from a node.js server. The server portion is very simple :
server.get(\'/orders\' function(req, res) {
res.se
This is what worked for me for IE 11+, Firefox and Chrome. In safari it downloads a file but as unknown and the filename is not set.
if (window.navigator.msSaveOrOpenBlob) {
var blob = new Blob([csvDataString]); //csv data string as an array.
// IE hack; see http://msdn.microsoft.com/en-us/library/ie/hh779016.aspx
window.navigator.msSaveBlob(blob, fileName);
} else {
var anchor = angular.element('<a/>');
anchor.css({display: 'none'}); // Make sure it's not visible
angular.element(document.body).append(anchor); // Attach to document for FireFox
anchor.attr({
href: 'data:attachment/csv;charset=utf-8,' + encodeURI(csvDataString),
target: '_blank',
download: fileName
})[0].click();
anchor.remove();
}
$http
service returns a promise
which has two callback methods as shown below.
$http({method: 'GET', url: '/someUrl'}).
success(function(data, status, headers, config) {
var anchor = angular.element('<a/>');
anchor.attr({
href: 'data:attachment/csv;charset=utf-8,' + encodeURI(data),
target: '_blank',
download: 'filename.csv'
})[0].click();
}).
error(function(data, status, headers, config) {
// handle error
});
Using angular 1.5.9
I made it working like this by setting the window.location to the csv file download url. Tested and its working with the latest version of Chrome and IE11.
Angular
$scope.downloadStats = function downloadStats{
var csvFileRoute = '/stats/download';
$window.location = url;
}
html
<a target="_self" ng-click="downloadStats()"><i class="fa fa-download"></i> CSV</a>
In php set the below headers for the response:
$headers = [
'content-type' => 'text/csv',
'Content-Disposition' => 'attachment; filename="export.csv"',
'Cache-control' => 'private, must-revalidate, post-check=0, pre-check=0',
'Content-transfer-encoding' => 'binary',
'Expires' => '0',
'Pragma' => 'public',
];
Most of the references on the web about this issue point out to the fact that you cannot download files via ajax call 'out of the box'. I have seen (hackish) solutions that involve iframes
and also solutions like @dcodesmith's that work and are perfectly viable.
Here's another solution I found that works in Angular and is very straighforward.
In the view, wrap the csv
download button with <a>
tag the following way :
<a target="_self" ng-href="{{csv_link}}">
<button>download csv</button>
</a>
(Notice the target="_self
there, it's crucial to disable Angular's routing inside the ng-app more about it here)
Inside youre controller you can define csv_link
the following way :
$scope.csv_link = '/orders' + $window.location.search;
(the $window.location.search
is optional and onlt if you want to pass additionaly search query to your server)
Now everytime you click the button, it should start downloading.
var anchor = angular.element('<a/>');
anchor.css({display: 'none'}); // Make sure it's not visible
angular.element(document.body).append(anchor); // Attach to document
anchor.attr({
href: 'data:attachment/csv;charset=utf-8,' + encodeURI(data),
target: '_blank',
download: 'filename.csv'
})[0].click();
anchor.remove(); // Clean it up afterwards
This code works both Mozilla and chrome