9

I need to provide a link to download a file, the link must be hidden and accessible by any users, Here is my code , there are no errors whatsoever, but I can't even get the download dialog box to open:

Template

 <a ng-href="#" target="page" type="button" class="btn" 
ng-click="download()">Download</a>

Script file

$scope.download = function(){
 //here i need to know the code,can anybody explain me
}
lin
  • 17,956
  • 4
  • 59
  • 83

2 Answers2

18

I had to achieve the functionality. Also had to make sure that it works for all the major supported browsers. Here's the solution for the same!!!

Happy Coding!!!

Your View/HTML

<a target="_self" class="ui right floated btn btn-warning" href ng-click="downloadInvoice()"> Download </a>

Your Controller

$scope.downloadInvoice = function () {
    $http.post(url,requestData, {responseType:'arraybuffer',headers:header
        })
            .success(function (response) {
                var file = new Blob([response], {type: 'application/pdf'});

                var isChrome = !!window.chrome && !!window.chrome.webstore;
                var isIE = /*@cc_on!@*/false || !!document.documentMode;
                var isEdge = !isIE && !!window.StyleMedia;


                if (isChrome){
                    var url = window.URL || window.webkitURL;

                    var downloadLink = angular.element('<a></a>');
                    downloadLink.attr('href',url.createObjectURL(file));
                    downloadLink.attr('target','_self');
                    downloadLink.attr('download', 'invoice.pdf');
                    downloadLink[0].click();
                }
                else if(isEdge || isIE){
                    window.navigator.msSaveOrOpenBlob(file,'invoice.pdf');

                }
                else {
                    var fileURL = URL.createObjectURL(file);
                    window.open(fileURL);
                }

            })
};
Sagar Desai
  • 347
  • 1
  • 3
  • 11
  • Really helpful;) I had to change only one thing: var file = new Blob([response], {type: 'application/pdf'}); to var file = new Blob([response.data], {type: 'application/pdf'}); – Mroczny Arturek Apr 15 '22 at 15:16
8

First of all, your can't "hide/not public" a link in a web based technology (HTML/CSS/JavaScript) application. Downloads are handled by the client, so the Download/Link-URL must be public. You can try to "hide" protective params like e.g. IDs in the download URL by using a backend executed programming language like "PHP or node.js, etc.". In that way you can create hash URLs like http://www.myside.com/download/359FTBW!S3T387IHS to hide parameters like the recordId in your URL.

By knowing this, your solution is pretty easy. Just use the HTML attribute download like <a href="http://mydownloadurl" download>link text</a> to force the browser to download the href source. No ng-click is needed here. Unfortunately the download attribute is not supported by Safari browser. This doesn't realy matter while the browser is handling the download itself. Depending on the users system OS configuration the file will be downloaded or directly opened in a programm installed on that system. For example, a PDF file will be opened in a PDF Viewer if some pdf viewer application is available.

I wrote a Plunker which handles ng-href in a AngularJS controller $scope. I hope this is what you need.

Your controller:

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.fileHref = 'http://www.analysis.im/uploads/seminar/pdf-sample.pdf';
});

Your view:

<head>
  <meta charset="utf-8" />
  <title>AngularJS Plunker</title>
  <script>
    document.write('<base href="' + document.location + '" />');
  </script>
  <link rel="stylesheet" href="style.css" />
  <script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.14/angular.js" data-semver="1.3.14"></script>
  <script src="app.js"></script>
</head>

<body ng-controller="MainCtrl">
  <a ng-href="fileHref" download="yourFilename">Download</a>
</body>
</html>
lin
  • 17,956
  • 4
  • 59
  • 83
  • ok thank you, supppose if we want to download file inside ng-click function.how can we achieve this and one more thing here i am seeing directly given href url .without giving directly I need to give inside ng-click function,can u tell please. – vallepu veerendra kumar Mar 06 '15 at 08:02
  • Make the download via angularJS is not a good way. But if you want to set the download URL via angularJS -> take a look at my example. – lin Mar 06 '15 at 08:48
  • sorry dude i am not able to vote here,minimum i must need 15 reputations for vote up any way i appreciate you.i will try to get and vote this in few a days,thank you. – vallepu veerendra kumar Mar 06 '15 at 10:45
  • Don't understand why you put `ng-href="{{ fileHref() }} "` instead of `ng-href=" fileHref() "` as `ng-href` is angular directive. But, it is working fine for interpolation not for second one. – Sai M. Dec 22 '16 at 10:31
  • I can't find link for download url via angularjs. Please provide it. – Sai M. Dec 22 '16 at 10:51
  • Thanks. I updated my answer and code to give more details about client side download handling. – lin Dec 22 '16 at 11:00
  • I don't want to use download attribute of HTML. Can I do that in angularjs/javascript way. – Sai M. Dec 22 '16 at 11:09
  • Its the AngularJS/JavaScript/HTML way. You cant force a real download because its allways handled by the client and the application installed on its OS. I explained that in my answer. You can only ensure that the client will trigger a real download without open a installed programm by using `download` attribute. For example click an mp3 link in your browser, it will play directly (I promise). By adding a `download` attribute to that `a` it will be downloaded instead of play. – lin Dec 22 '16 at 11:17
  • But, I want some file to be downloaded when ever the app is visited. – Sai M. Dec 22 '16 at 11:43
  • So fire a click event on that link like `angular.element('#myselector').triggerHandler('click');` when ever the app is visted. – lin Dec 22 '16 at 14:22
  • @lin: The solution is nice. But, this solution is not working for "Authorization: Bearer" token thing or when the content can not be downloaded in unauthorized way. Can you please give a solution for it? – Anijit Sau Aug 17 '17 at 13:03
  • @Anijit https://stackoverflow.com/questions/16592709/using-javascript-to-add-custom-http-header-and-trigger-file-download – lin Aug 17 '17 at 13:21
  • The `download` attribute is not supported in IE11 (latest version on Windows 7) and on iOS Safari: https://caniuse.com/#feat=download – AsGoodAsItGets Jun 21 '18 at 12:17