web-dev-qa-db-fra.com

téléchargez le fichier csv de web api en js angulaire

mon contrôleur API renvoie un fichier csv comme indiqué ci-dessous:

    [HttpPost]
    public HttpResponseMessage GenerateCSV(FieldParameters fieldParams)
    {
        var output = new byte[] { };
        if (fieldParams!= null)
        {
            using (var stream = new MemoryStream())
            {
                this.SerializeSetting(fieldParams, stream);
                stream.Flush();
                output = stream.ToArray();
            }
        }
        var result = new HttpResponseMessage(HttpStatusCode.OK) { Content = new ByteArrayContent(output) };
        result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
        result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
        {
            FileName = "File.csv"
        };
        return result;
    }

et mes angularjs qui vont envoyer et recevoir le fichier csv sont affichés ci-dessous:

$scope.save = function () {
            var csvInput= extractDetails();

            // File is an angular resource. We call its save method here which
            // accesses the api above which should return the content of csv
            File.save(csvInput, function (content) {
                var dataUrl = 'data:text/csv;utf-8,' + encodeURI(content);
                var hiddenElement = document.createElement('a');
                hiddenElement.setAttribute('href', dataUrl);
                hiddenElement.click();
            });
        };

En chrome, il télécharge un fichier appelé document mais n’ayant aucune extension de type de fichier . Le contenu du fichier est [Object object].

Dans IE10, rien n'est téléchargé.

Que pourrais-je faire pour résoudre ce problème? 

UPDATE: Cela pourrait fonctionner pour vous autres avec le même problème: link

48
raberana

Essayez comme ça:

File.save(csvInput, function (content) {
    var hiddenElement = document.createElement('a');

    hiddenElement.href = 'data:attachment/csv,' + encodeURI(content);
    hiddenElement.target = '_blank';
    hiddenElement.download = 'myFile.csv';
    hiddenElement.click();
});

basé sur la plus excellente réponse dans cette question

62
adeneo

J'ai utilisé la solution ci-dessous et cela a fonctionné pour moi.

 if (window.navigator.msSaveOrOpenBlob) {
   var blob = new Blob([decodeURIComponent(encodeURI(result.data))], {
     type: "text/csv;charset=utf-8;"
   });
   navigator.msSaveBlob(blob, 'filename.csv');
 } else {
   var a = document.createElement('a');
   a.href = 'data:attachment/csv;charset=utf-8,' + encodeURI(result.data);
   a.target = '_blank';
   a.download = 'filename.csv';
   document.body.appendChild(a);
   a.click();
 }

9
Manu Sharma

Aucun de ceux qui ont fonctionné pour moi dans Chrome 42 ...

Au lieu de cela ma directive utilise maintenant cette fonction link (base64 l'a fait fonctionner):

  link: function(scope, element, attrs) {
    var downloadFile = function downloadFile() {
      var filename = scope.getFilename();
      var link = angular.element('<a/>');
      link.attr({
        href: 'data:attachment/csv;base64,' + encodeURI($window.btoa(scope.csv)),
        target: '_blank',
        download: filename
      })[0].click();
      $timeout(function(){
        link.remove();
      }, 50);
    };

    element.bind('click', function(e) {
      scope.buildCSV().then(function(csv) {
        downloadFile();
      });
      scope.$apply();
    });
  }
4
malix

La dernière réponse a fonctionné pour moi pendant quelques mois, puis a cessé de reconnaître le nom de fichier, comme le commentait adeneo ... 

La réponse de @ Scott ici fonctionne pour moi:

Téléchargez le fichier à partir d’une méthode d’API Web ASP.NET avec AngularJS

4
prsnca

J'ai dû implémenter ceci récemment. Pensée de partager ce que j'avais trouvé;

Pour que cela fonctionne dans Safari, je devais définir la cible: '_self' ,. Ne vous inquiétez pas du nom de fichier dans Safari. On dirait que ce n'est pas supporté comme mentionné ici; https://github.com/konklone/json/issues/56 ( http://caniuse.com/#search=download )

Le code ci-dessous fonctionne très bien pour moi dans Mozilla, Chrome & Safari;

  var anchor = angular.element('<a/>');
  anchor.css({display: 'none'});
  angular.element(document.body).append(anchor);
  anchor.attr({
    href: 'data:attachment/csv;charset=utf-8,' + encodeURIComponent(data),
    target: '_self',
    download: 'data.csv'
  })[0].click();
  anchor.remove();
2
Ricky Boy

Dans Angular 1.5, utilisez le service $window pour télécharger un fichier.

angular.module('app.csv').factory('csvService', csvService);

csvService.$inject = ['$window'];

function csvService($window) {
    function downloadCSV(urlToCSV) {
        $window.location = urlToCSV;
    }
}
1
user2601995

Plutôt que d'utiliser Ajax/XMLHttpRequest/$ http pour appeler votre méthode WebApi, utilisez un formulaire HTML. Ainsi, le navigateur enregistre le fichier à l'aide des informations de nom de fichier et de type de contenu figurant dans les en-têtes de réponse. Il n'est pas nécessaire de contourner les limitations de JavaScript pour la gestion des fichiers. Vous pouvez également utiliser une méthode GET plutôt qu'un POST lorsque la méthode renvoie des données. Voici un exemple de formulaire:

<form name="export" action="/MyController/Export" method="get" novalidate>
    <input name="id" type="id" ng-model="id" placeholder="ID" />
    <input name="fileName" type="text" ng-model="filename" placeholder="file name" required />
    <span class="error" ng-show="export.fileName.$error.required">Filename is required!</span>
    <button type="submit" ng-disabled="export.$invalid">Export</button>
</form>
1
Paul Taylor

Je pense que la meilleure façon de télécharger un fichier généré par l'appel de REST est d'utiliser window.location Exemple: 

    $http({
        url: url,
        method: 'GET'
    })
    .then(function scb(response) {
        var dataResponse = response.data;
        //if response.data for example is : localhost/export/data.csv
        
        //the following will download the file without changing the current page location
        window.location = 'http://'+ response.data
    }, function(response) {
      showWarningNotification($filter('translate')("global.errorGetDataServer"));
    });

0
Fadi Nouh

Le fichier a.download n'est pas pris en charge par IE. Au moins sur les pages HTML5 "prises en charge". :(

0
Nick Jacobs