baixar arquivo csv da web api em js angular

meu controlador de API está retornando um arquivo csv como visto abaixo:

[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; } 

e meu angularjs que enviará e receberá o arquivo csv é mostrado abaixo:

 $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(); }); }; 

No chrome, ele faz o download de um arquivo chamado document mas não possui extensão de tipo de arquivo. O conteúdo do arquivo é [Object object] .

No IE10, nada é baixado.

O que eu poderia fazer para consertar isso?

ATUALIZAÇÃO: Isso pode funcionar para vocês com o mesmo problema: link

Experimente como:

 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(); }); 

com base na resposta mais excelente nesta questão

Eu usei a solução abaixo e funcionou para mim.

  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(); } 

Nenhum deles funcionou para mim no Chrome 42 …

Em vez disso, minha diretiva agora usa essa function de link ( base64 fez isso funcionar):

  link: function(scope, element, attrs) { var downloadFile = function downloadFile() { var filename = scope.getFilename(); var link = angular.element(''); 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(); }); } 

A última resposta funcionou para mim por alguns meses, depois parou de reconhecer o nome do arquivo, como adeneo comentou …

@ Resposta de Scott aqui está trabalhando para mim:

Baixar arquivo de um método de API da Web do ASP.NET usando o AngularJS

Eu tive que implementar isso recentemente. Pensei em compartilhar o que eu havia descoberto;

Para fazer isso funcionar no Safari, eu tive que definir o destino: ‘_self’. Não se preocupe com o nome do arquivo no Safari. Parece que não é suportado como mencionado aqui; https://github.com/konklone/json/issues/56 ( http://caniuse.com/#search=download )

O código abaixo funciona bem para mim no Mozilla, Chrome e Safari;

  var anchor = angular.element(''); 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(); 

O a.download não é suportado pelo IE. Pelo menos nas páginas “suportadas” do HTML5. 🙁

Em vez de usar Ajax / XMLHttpRequest / $ http para invocar seu método WebApi, use um formulário html. Dessa forma, o navegador salva o arquivo usando as informações de nome de arquivo e tipo de conteúdo nos headers de resposta, e você não precisa contornar as limitações do javascript no processamento de arquivos. Você também pode usar um método GET em vez de um POST, pois o método retorna dados. Aqui está um exemplo:

 
Filename is required!

Em Angular 1.5, use o serviço $window para baixar um arquivo.

 angular.module('app.csv').factory('csvService', csvService); csvService.$inject = ['$window']; function csvService($window) { function downloadCSV(urlToCSV) { $window.location = urlToCSV; } } 

Acho que a melhor maneira de baixar qualquer arquivo gerado pela chamada REST é usar o exemplo window.location:

  $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")); });