web-dev-qa-db-fra.com

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 serveur node.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 angular 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 examiné d'autres réponses concernant le téléchargement de fichiers depuis le serveur dans Angular, mais je n'ai rien trouvé qui puisse fonctionner pour moi. Y a-t-il une manière commune de faire ceci? On dirait que quelque chose devrait être simple.

55
Michael

$http service renvoie un promise qui possède 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
  });
111
dcodesmith
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 sur Mozilla et sur Chrome

21
Komal Singh

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 un appel ajax 'out of the box'. J'ai vu (bidouiller) des solutions qui impliquent iframes ainsi que des solutions comme @dcodesmith qui fonctionnent et sont parfaitement viables.

Voici une autre solution que j'ai trouvée qui fonctionne dans Angular et qui est très simple.

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

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

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

Dans votre contrôleur , vous pouvez définir csv_link la manière suivante:

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

(le $window.location.search est facultatif et uniquement si vous souhaitez transmettre une requête de recherche à votre serveur)

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

21
Michael

C’est ce qui a fonctionné pour moi pour IE 11+, Firefox et Chrome. Dans Safari, il télécharge un fichier mais en tant qu’inconnu et le nom du 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
Nilath

Utilisation de angular 1.5.9

Je l'ai fait fonctionner comme ceci en définissant le window.location à l'URL de téléchargement du fichier CSV. Testé et fonctionne 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
forsimb