Angularjs简单的文件下载
HTML:
<a href="mysite.com/uploads/asd4a4d5a.pdf" download="foo.pdf">
在数据库中保存真实姓名时,上传将获得唯一的文件名。 我想实现一个简单的文件下载。 但是上面的代码redirect到/因为:
$routeProvider.otherwise({ redirectTo: '/', controller: MainController });
我试着用
$scope.download = function(resource){ window.open(resource); }
但是这只是在新窗口中打开文件。
任何想法如何启用一个真正的下载任何文件types?
https://docs.angularjs.org/guide/$location#html-link-rewriting
在以下情况下,链接不会被重写。 相反,浏览器将执行整个页面重新加载到原始链接。
包含目标元素的链接示例:
<a href="/ext/link?a=b" target="_self">link</a>
进入不同域的绝对链接示例:
<a href="http://angularjs.org/">link</a>
以'/'开头的链接,在定义基数时导致不同的基本path示例:
<a href="/not-my-base/link">link</a>
所以在你的情况下,你应该像这样添加一个目标属性…
<a target="_self" href="example.com/uploads/asd4a4d5a.pdf" download="foo.pdf">
我们还必须开发一个解决scheme,甚至可以与需要身份validation的API一起工作(请参阅本文 )
简单地使用AngularJS这里是我们如何做到的:
第1步:创build一个专用的指令
// jQuery needed, uses Bootstrap classes, adjust the path of templateUrl app.directive('pdfDownload', function() { return { restrict: 'E', templateUrl: '/path/to/pdfDownload.tpl.html', scope: true, link: function(scope, element, attr) { var anchor = element.children()[0]; // When the download starts, disable the link scope.$on('download-start', function() { $(anchor).attr('disabled', 'disabled'); }); // When the download finishes, attach the data to the link. Enable the link and change its appearance. scope.$on('downloaded', function(event, data) { $(anchor).attr({ href: 'data:application/pdf;base64,' + data, download: attr.filename }) .removeAttr('disabled') .text('Save') .removeClass('btn-primary') .addClass('btn-success'); // Also overwrite the download pdf function to do nothing. scope.downloadPdf = function() { }; }); }, controller: ['$scope', '$attrs', '$http', function($scope, $attrs, $http) { $scope.downloadPdf = function() { $scope.$emit('download-start'); $http.get($attrs.url).then(function(response) { $scope.$emit('downloaded', response.data); }); }; }] });
第2步:创build一个模板
<a href="" class="btn btn-primary" ng-click="downloadPdf()">Download</a>
第3步:使用它
<pdf-download url="/some/path/to/a.pdf" filename="my-awesome-pdf"></pdf-download>
这将呈现一个蓝色的button。 点击后,将下载PDF(注意:后端必须以Base64编码forms提供PDF)并放入href中。 该button变成绿色,并将文本切换到保存 。 用户可以再次点击,并会显示文件my-awesome.pdf的标准下载文件对话框。
我们的例子使用PDF文件,但显然你可以提供任何二进制格式,因为它是正确的编码。
如果您需要一个更高级的指令,我推荐我实现的解决scheme,在Internet Explorer 11,Chrome和FireFox上正确testing。
我希望这将是有益的。
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('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'); } } }); } } })
在控制器中:
$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=[]; }); };
在服务中:
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(在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; }
在模板中
<md-button class="md-fab md-mini md-warn md-ink-ripple" ng-click="export()" aria-label="Export"> <md-icon class="material-icons" alt="Export" title="Export" aria-label="Export"> system_update_alt </md-icon></md-button>
在控制器中
$scope.export = function(){ $window.location.href = $scope.export; };
我知道这是一个旧的post,但我有麻烦得到任何解决scheme的堆栈交换工作自动下载一个Angular的post。
这是我的解决scheme(jQuery / Angular / PHP的混合):
PHP
return array($filename,$url);
angular度视图
<a target="_self" id="downloadpdf" href={{downloadurl}} download={{filename}} style="display: none"></a>
angular度控制器
一旦收到与url和文件名的响应:
$scope.downloadurl=data[1]; $scope.filename=data[0]; setTimeout(function () { $('#downloadpdf')[0].click(); }, 1000);
我把这个延迟了1秒,以便给这些值填充时间,因为有时候执行得太快了。
希望它有帮助!