Télécharger le contenu texte / csv sous forme de fichiers à partir du serveur dans Angular

J'essaie de diffuser un fichier csv à partir d'un nœud.serveur js. La partie serveur est très simple :

server.get('/orders' function(req, res) {
  res.setHeader('content-type', 'text/csv');
  res.setHeader('content-disposition', 'attachment; filename='orders.csv');
  return orders.pipe(res); // assuming orders is a csv file readable stream (doesn't have to be a stream, can be a normal response)
}

Dans mon contrôleur angulaire, j'essaie de faire quelque chose comme ceci

$scope.csv = function() {
    $http({method: 'GET', url: '/orders'});
};

Cette fonction est appelée quand il y a un clic sur un bouton avec ng-click, à mon avis :

<button ng-click="csv()">.csv</button>

J'ai regardé d'autres réponses sur le téléchargement de fichiers à partir du serveur dans Angular, mais je n'ai rien trouvé qui fonctionnait pour moi. Y a-t-il un moyen commun de le faire ? On dirait quelque chose qui devrait être simple.

52
demandé sur dcodesmith 2014-01-03 16:54:40

5 réponses

$http service renvoie un promise qui a deux méthodes de rappel comme indiqué ci-dessous.

$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
  });
108
répondu dcodesmith 2016-02-24 16:20:59

La plupart des références sur le web à propos de ce problème soulignent le fait que vous ne pouvez pas télécharger de fichiers via l'appel ajax 'out of the box'. J'ai vu des solutions (hackish) qui impliquent iframes et aussi des solutions comme @dcodesmith qui fonctionnent et sont parfaitement viables.

Voici une autre solution que j'ai trouvée qui fonctionne en angulaire et est très directe.

Dans la vue , enveloppez le bouton de téléchargement csv avec la balise <a> de la manière suivante :

<a target="_self" ng-href="{{csv_link}}">
  <button>download csv</button>
</a>

(Notez le target="_self là, il est crucial de désactiver le routage D'Angular dans l'application ng-app plus à ce sujet ici)

À l'Intérieur de youre contrôleur, vous pouvez définir csv_link de la façon suivante :

$scope.csv_link = '/orders' + $window.location.search;

(le {[7] } est facultatif et onlt si vous voulez passer la requête de recherche supplémentaire à votre serveur)

Maintenant, chaque fois que vous cliquez sur le bouton, il devrait commencer à télécharger.

21
répondu Michael 2017-05-23 12:34:27
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

Ce code fonctionne à la fois Mozilla et chrome

21
répondu Komal Singh 2015-08-07 07:01:01

C'est ce qui a fonctionné pour moi pour IE 11+, Firefox et Chrome. Dans safari, il télécharge un fichier mais comme inconnu et le nom de fichier n'est pas défini.

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();
}
7
répondu Nilath 2016-02-17 05:35:53

En utilisant angular 1.5.9

Je l'ai fait fonctionner comme ça en définissant la fenêtre.emplacement de l'url de téléchargement du fichier csv. Testé et son travail avec la dernière version de Chrome et IE11.

Angulaire

   $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>

Dans php définissez les en-têtes ci-dessous pour la réponse:

$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',
];
0
répondu forsimb 2017-07-24 19:36:55