How do you serve a file for download with AngularJS or Javascript?

JavascriptAngularjs

Javascript Problem Overview


I have some text in a hidden textarea. When a button is clicked I would like to have the text offered for download as a .txt file. Is this possible using AngularJS or Javascript?

Javascript Solutions


Solution 1 - Javascript

You can do something like this using Blob.

<a download="content.txt" ng-href="{{ url }}">download</a>

in your controller:

var content = 'file content for example';
var blob = new Blob([ content ], { type : 'text/plain' });
$scope.url = (window.URL || window.webkitURL).createObjectURL( blob );

in order to enable the URL:

app = angular.module(...);
app.config(['$compileProvider',
    function ($compileProvider) {
        $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|tel|file|blob):/);
}]);

Please note that

> Each time you call createObjectURL(), a new object URL is created, even if you've already created one for the same object. Each of these must be released by calling URL.revokeObjectURL() when you no longer need them. Browsers will release these automatically when the document is unloaded; however, for optimal performance and memory usage, if there are safe times when you can explicitly unload them, you should do so.

Source: MDN

Solution 2 - Javascript

Just click the button to download using following code.

in html

<a class="btn" ng-click="saveJSON()" ng-href="{{ url }}">Export to JSON</a>

In controller

$scope.saveJSON = function () {
			$scope.toJSON = '';
			$scope.toJSON = angular.toJson($scope.data);
			var blob = new Blob([$scope.toJSON], { type:"application/json;charset=utf-8;" });			
			var downloadLink = angular.element('<a></a>');
                        downloadLink.attr('href',window.URL.createObjectURL(blob));
                        downloadLink.attr('download', 'fileName.json');
			downloadLink[0].click();
		};

Solution 3 - Javascript

Try this

<a target="_self" href="mysite.com/uploads/ahlem.pdf" download="foo.pdf">

and visit this site it could be helpful for you :)

http://docs.angularjs.org/guide/

Solution 4 - Javascript

This can be done in javascript without the need to open another browser window.

window.location.assign('url');

Replace 'url' with the link to your file. You can put this in a function and call it with ng-click if you need to trigger the download from a button.

Solution 5 - Javascript

In our current project at work we had a invisible iFrame and I had to feed the url for the file to the iFrame to get a download dialog box. On the button click, the controller generates the dynamic url and triggers a $scope event where a custom directive I wrote, is listing. The directive will append a iFrame to the body if it does not exist already and sets the url attribute on it.

EDIT: Adding a directive

appModule.directive('fileDownload', function ($compile) {
    var fd = {
        restrict: 'A',
        link: function (scope, iElement, iAttrs) {

            scope.$on("downloadFile", function (e, url) {
                var iFrame = iElement.find("iframe");
                if (!(iFrame && iFrame.length > 0)) {
                    iFrame = $("<iframe style='position:fixed;display:none;top:-1px;left:-1px;'/>");
                    iElement.append(iFrame);
                }

                iFrame.attr("src", url);


            });
        }
    };

    return fd;
});

This directive responds to a controller event called downloadFile

so in your controller you do

$scope.$broadcast("downloadFile", url);

Solution 6 - Javascript

You can set location.href to a data URI containing the data you want to let the user download. Besides this, I don't think there's any way to do it with just JavaScript.

Solution 7 - Javascript

Would just like to add that in case it doesn't download the file because of unsafe:blob:null... when you hover over the download button, you have to sanitize it. For instance,

> var app = angular.module('app', []); > > app.config(function($compileProvider){ > > $compileProvider.aHrefSanitizationWhitelist(/^\s*(|blob|):/);

Solution 8 - Javascript

If you have access to on the server, consider setting headers as answered in this more general question.

Content-Type: application/octet-stream
Content-Disposition: attachment;filename=\"filename.xxx\"

Reading the comments on that answer, it is advisable to use a more specific Content-Type than octet-stream.

Solution 9 - Javascript

I had teh same problem and spend many hours find diferent solutions, and now I join all the comments in this post.I hope it, will be helpfull, my answer was correctly tested on Internet Explorer 11, Chrome and FireFox.

HTML :

<a href="#" class="btn btn-default" file-name="'fileName.extension'"  ng-click="getFile()" file-download="myBlobObject"><i class="fa fa-file-excel-o"></i></a>

DIRECTIVE :

directive('fileDownload',function(){
	return{
		restrict:'A',
		scope:{
			fileDownload:'=',
			fileName:'=',
		},
		
		link:function(scope,elem,atrs){
			

			scope.$watch('fileDownload',function(newValue, oldValue){
				
				if(newValue!=undefined && newValue!=null){
					console.debug('Downloading a new file'); 
					var isFirefox = typeof InstallTrigger !== 'undefined';
					var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
					var isIE = /*@cc_on!@*/false || !!document.documentMode;
					var isEdge = !isIE && !!window.StyleMedia;
					var isChrome = !!window.chrome && !!window.chrome.webstore;
					var isOpera = (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
					var isBlink = (isChrome || isOpera) && !!window.CSS;
					
					if(isFirefox || isIE || isChrome){
						if(isChrome){
							console.log('Manage Google Chrome download');
							var url = window.URL || window.webkitURL;
			                var fileURL = url.createObjectURL(scope.fileDownload);
							var downloadLink = angular.element('<a></a>');//create a new  <a> tag element
	                        downloadLink.attr('href',fileURL);
	                        downloadLink.attr('download',scope.fileName);
	                        downloadLink.attr('target','_self');
	                        downloadLink[0].click();//call click function
		                    url.revokeObjectURL(fileURL);//revoke the object from URL
						}
						if(isIE){
							console.log('Manage IE download>10');
					        window.navigator.msSaveOrOpenBlob(scope.fileDownload,scope.fileName); 
						}
						if(isFirefox){
							console.log('Manage Mozilla Firefox download');
							var url = window.URL || window.webkitURL;
			                var fileURL = url.createObjectURL(scope.fileDownload);
							var a=elem[0];//recover the <a> tag from directive
							a.href=fileURL;
							a.download=scope.fileName;
							a.target='_self';
							a.click();//we call click function
						}
						
						
					}else{
						alert('SORRY YOUR BROWSER IS NOT COMPATIBLE');
					}
				}
			});
			
		}
	}
})

IN CONTROLLER:

$scope.myBlobObject=undefined;
$scope.getFile=function(){
		console.log('download started, you can show a wating animation');
		serviceAsPromise.getStream({param1:'data1',param1:'data2', ...})
   		.then(function(data){//is important that the data was returned as Aray Buffer
   		        console.log('Stream download complete, stop animation!');
   				$scope.myBlobObject=new Blob([data],{ type:'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
   		},function(fail){
   				console.log('Download Error, stop animation and show error message');
   									$scope.myBlobObject=[];
   								});
   							}; 

IN SERVICE:

function getStream(params){
				 console.log("RUNNING");
				 var deferred = $q.defer();
				 
				 $http({
					 url:'../downloadURL/',
					 method:"PUT",//you can use also GET or POST
					 data:params,
					 headers:{'Content-type': 'application/json'},
				 	 responseType : 'arraybuffer',//THIS IS IMPORTANT
				 	})
	                .success(function (data) {
	                	console.debug("SUCCESS");
	                	deferred.resolve(data);
	                }).error(function (data) {
	                	 console.error("ERROR");
	                	 deferred.reject(data);
	                });
				 
				 return deferred.promise;
				};

BACKEND(on SPRING):

@RequestMapping(value = "/downloadURL/", method = RequestMethod.PUT)
public void downloadExcel(HttpServletResponse response,
		@RequestBody Map<String,String> spParams
		) throws IOException {
		OutputStream outStream=null;
outStream = response.getOutputStream();//is important manage the exceptions here
ObjectThatWritesOnOutputStream myWriter= new ObjectThatWritesOnOutputStream();// note that this object doesn exist on JAVA,
ObjectThatWritesOnOutputStream.write(outStream);//you can configure more things here
outStream.flush();
return;
}

Solution 10 - Javascript

This worked for me in angular:

var a = document.createElement("a");
a.href = 'fileURL';
a.download = 'fileName';
a.click();

Solution 11 - Javascript

I didnt want Static Url. I have AjaxFactory for doing all ajax operations. I am getting url from the factory and binding it as follows.

<a target="_self" href="{{ file.downloadUrl + '/' + order.OrderId + '/' + fileName }}" download="{{fileName}}">{{fileName}}</a>

Thanks @AhlemMustapha

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionnickponlineView Question on Stackoverflow
Solution 1 - JavascriptToshView Answer on Stackoverflow
Solution 2 - JavascriptAmrutView Answer on Stackoverflow
Solution 3 - JavascriptAhlemMustaphaView Answer on Stackoverflow
Solution 4 - Javascriptmm8154View Answer on Stackoverflow
Solution 5 - JavascriptKetanView Answer on Stackoverflow
Solution 6 - JavascriptJani HartikainenView Answer on Stackoverflow
Solution 7 - JavascriptSamir AlajmovicView Answer on Stackoverflow
Solution 8 - Javascriptplong0View Answer on Stackoverflow
Solution 9 - JavascripthavelinoView Answer on Stackoverflow
Solution 10 - JavascriptZohab AliView Answer on Stackoverflow
Solution 11 - Javascriptom471987View Answer on Stackoverflow