Il download semplice dei file di Angularjs causa il reindirizzamento del router

HTML:

 

I caricamenti ottengono un nome di file univoco mentre il nome reale viene mantenuto nel database. Voglio realizzare un semplice download di file. Ma il codice sopra reindirizza a / a causa di:

 $routeProvider.otherwise({ redirectTo: '/', controller: MainController }); 

Ci ho provato

 $scope.download = function(resource){ window.open(resource); } 

ma questo apre semplicemente il file in una nuova finestra.

Qualche idea su come abilitare un vero download per qualsiasi tipo di file?

https://docs.angularjs.org/guide/$location#html-link-rewriting

In casi come i seguenti, i collegamenti non vengono riscritti; invece, il browser eseguirà una pagina intera ricaricata sul link originale.

  • Collegamenti contenenti elementi di destinazione Esempio:
    link

  • Link assoluti che vanno a un dominio diverso Esempio:
    link

  • Collegamenti che iniziano con ‘/’ che portano a un percorso di base diverso quando viene definita la base Esempio:
    link

Quindi nel tuo caso, dovresti aggiungere un attributo target come …

  

Abbiamo anche dovuto sviluppare una soluzione che funzionasse anche con le API che richiedono l’autenticazione (vedi questo articolo )

Utilizzando AngularJS in poche parole ecco come l’abbiamo fatto:

Passaggio 1: creare una direttiva dedicata

 // jQuery needed, uses Bootstrap classs, 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); }); }; }] }); 

Passaggio 2: crea un modello

 Download 

Step 3: usalo

  

Questo renderà un pulsante blu. Quando si fa clic, verrà scaricato un PDF (Attenzione: il backend deve consegnare il PDF nella codifica Base64!) E inserirlo nell’href. Il pulsante diventa verde e cambia il testo in Salva . L’utente può fare nuovamente clic e verrà presentata una finestra di dialogo di download standard per il file my-awesome.pdf .

Il nostro esempio utilizza file PDF, ma a quanto pare è ansible fornire qualsiasi formato binario dato che è codificato correttamente.

Se hai bisogno di una direttiva più avanzata, ti consiglio la soluzione che ho implementato, correttamente testata su Internet Explorer 11, Chrome e FireFox.

Lo spero, sarà utile.

HTML:

  

DIRETTIVA:

 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 = /*@[email protected]*/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('');//create a new  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  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 SERVIZIO:

 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 (su SPRING):

 @RequestMapping(value = "/downloadURL/", method = RequestMethod.PUT) public void downloadExcel(HttpServletResponse response, @RequestBody Map 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; } 

nel modello

   system_update_alt  

nel controller

  $scope.export = function(){ $window.location.href = $scope.export; }; 

So che questo è un vecchio post, ma ho avuto problemi a trovare una soluzione sullo scambio di stack che funzionasse per un download automatico con un post angular.

Ecco la mia soluzione (Un ibrido di jquery / Angular / php):

PHP

  return array($filename,$url); 

Vista angular

   

Controller angular

una volta ricevuta la risposta con l’url e il nome del file:

  $scope.downloadurl=data[1]; $scope.filename=data[0]; setTimeout(function () { $('#downloadpdf')[0].click(); }, 1000); 

Ho messo questo su un ritardo di 1 secondo per dare il tempo per popolare i valori perché era in esecuzione troppo veloce a volte.

Spero che sia d’aiuto!