Phil Sandler
Phil Sandler

Reputation: 28036

Using Angular to Download a File via Ajax

I have a service that generates a CSV file and returns it to the page via an http/ajax get. I'd like a user to click a button, have the service get called, and then have the file get downloaded to the user's browser.

I would like to do this The Angular Way, although I recognize this may have more to do with Ajax or the browser than Anguler per se.

The service is in C#, and this is what it returns:

return File(Encoding.UTF8.GetBytes(WriteCSV(assetList)), "text/csv", "results.csv");

The controller code that calls the service looks like the following. It works, but I don't know what to do on success:

$scope.exportCSV = function () {
    $http({
        method: "get",
        url: "ExportCSV"
    }).
        error(function (data, status, headers, config) {
            alert("Error exporting data to CSV.");
        });
};

Upvotes: 4

Views: 4088

Answers (2)

michael salmon
michael salmon

Reputation: 416

Possibly a more 'angulary' way is to have your controller set a flag to trigger the download, but put the core functionality in a directive that builds an element with a "download" attribute, and on display, a callback/watch calls the ng-click.

For example:

// put this in a template related to a given controller
<downloader ng-if="downloadready"></downloader>

// controller just needs to trigger the directive into action
module.controller(..., function($scope){
    $scope.downloadready = true; // trigger the directive to be created       
});

// and the directive code will build the element and click the button
module.directive('downloader', function ($compile) {
  return {
          restrict: 'E',
          replace: true,
          // values here can be placed in the template as variables and accessed in link()
          // but this is shortest to get the idea across
          template: '<a id="downloadbtn" class="btn" download="backup.json"></a>',
          link:function (scope, elm, attrs) {
              // this clicks the button outside the digest loop which the scope was updated in
              $timeout(function() {
                angular.element($('#downloadbtn')).triggerHandler('click');
              }, 0);
          }
     }
});

Though I admit, it's more mind-bending than changing redirect on window.location.

Upvotes: 2

Jason Jong
Jason Jong

Reputation: 4330

You can't initiate a download from a normal ajax GET or POST, you have to do the traditional way, eg window.location='url' and set the correct http header with the correct content-type which will prompt the download dialog in the users browser

Upvotes: 5

Related Questions