pobierz plik csv z web api w angular js

Mój kontroler API zwraca plik csv, jak pokazano poniżej:

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

A moje angularjs, które będą wysyłać i odbierać plik csv, pokazano poniżej:

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

W chrome pobiera plik o nazwie document, ale nie ma rozszerzenia typu pliku. Zawartość pliku to [Object object].

W IE10 nic nie jest pobierane.

Co mogę zrobić, żeby to naprawić?

UPDATE: To może zadziałać dla Was z tym samym problemem: link

Author: Community, 2013-11-30

9 answers

Spróbuj tak:

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

Na podstawie najdoskonalszej odpowiedzi w to pytanie

 60
Author: adeneo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:08

Użyłem poniższego rozwiązania i zadziałało na mnie.

 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();
 }
 8
Author: Manu Sharma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-30 02:54:42

Żadne z nich nie działało u mnie w Chrome 42...

Zamiast tego moja dyrektywa używa teraz funkcji link (base64 sprawiła, że działa):

  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
Author: malix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-08 04:29:43

Ostatnia odpowiedź działała u mnie przez kilka miesięcy, po czym przestała rozpoznawać nazwę pliku, jak skomentował adeneo ...

@Scott ' s answer here is working for me:

Pobierz Plik z ASP.NET metoda Web API przy użyciu AngularJS

 4
Author: prsnca,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:17:51

Ostatnio musiałem to wdrożyć. Pomyślałem, że podzielę się tym, co wymyśliłem;

Aby to działało w Safari, musiałem ustawić target: '_self',. Nie martw się o nazwę pliku w Safari. Wygląda na to, że nie jest obsługiwany, jak wspomniano tutaj; https://github.com/konklone/json/issues/56 (http://caniuse.com/#search=download )

Poniższy kod działa dobrze dla mnie w Mozilli, 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
Author: Ricky Boy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-13 00:58:19

A. download nie jest obsługiwany przez IE. Przynajmniej na stronach HTML5 "obsługiwane". :(

 1
Author: Nick Jacobs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-30 17:58:20

Zamiast używać Ajax / XMLHttpRequest / $http do wywoływania metody WebApi, użyj formularza html. W ten sposób przeglądarka zapisuje plik, używając nazwy pliku i informacji o typie zawartości w nagłówkach odpowiedzi, a ty nie musisz obejść ograniczeń javascript dotyczących obsługi plików. Możesz również użyć metody GET zamiast postu, ponieważ metoda zwraca dane. Oto przykładowa forma:

<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
Author: Paul Taylor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-18 11:44:19

W Angular 1.5 Użyj usługi $window, Aby pobrać plik.

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

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

function csvService($window) {
    function downloadCSV(urlToCSV) {
        $window.location = urlToCSV;
    }
}
 1
Author: user2601995,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-28 18:54:06

Myślę, że najlepszym sposobem na pobranie dowolnego pliku wygenerowanego przez wywołanie REST jest użycie window.położenie przykład:

    $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
Author: Fadi Nouh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-12 08:12:42