Scarica più file con una singola azione

Non sono sicuro che ciò sia ansible utilizzando le tecnologie web standard.

Voglio che l’utente sia in grado di scaricare più file in un’unica azione. Questo è fare clic sulle caselle di controllo accanto ai file e quindi ottenere tutti i file che sono stati controllati.

È ansible – se sì, quale strategia di base raccomandi. So che posso usare la tecnologia delle comete per creare eventi lato server che triggersno un HttpResponse ma spero che ci sia un modo più semplice.

HTTP non supporta più di un download di file alla volta.

Ci sono due soluzioni:

  • Apri x quantità di windows per avviare il download dei file (questo sarebbe fatto con JavaScript)
  • soluzione preferita creare uno script per comprimere i file
var links = [ 'https://s3.amazonaws.com/Minecraft.Download/launcher/Minecraft.exe', 'https://s3.amazonaws.com/Minecraft.Download/launcher/Minecraft.dmg', 'https://s3.amazonaws.com/Minecraft.Download/launcher/Minecraft.jar' ]; function downloadAll(urls) { var link = document.createElement('a'); link.setAttribute('download', null); link.style.display = 'none'; document.body.appendChild(link); for (var i = 0; i < urls.length; i++) { link.setAttribute('href', urls[i]); link.click(); } document.body.removeChild(link); } 
  

Puoi creare una serie temporanea di iframe nascosti, avviare il download tramite GET o POST al loro interno, attendere l’avvio dei download e rimuovere gli iframe:

         

Oppure, senza jQuery:

  function download(...urls) { urls.forEach(url => { let iframe = document.createElement('iframe'); iframe.style.visibility = 'collapse'; document.body.append(iframe); iframe.contentDocument.write( `
` ); iframe.contentDocument.forms[0].submit(); setTimeout(() => iframe.remove(), 2000); }); }

Questa soluzione funziona su tutti i browser e non triggers avvisi. Piuttosto che creare un iframe , qui creiamo un link per ogni file. Ciò impedisce l’apparizione di messaggi di avvertimento.

Per gestire la parte di loop, usiamo setTimeout , che è necessario che funzioni in IE.

 /** * Download a list of files. * @author speedplane */ function download_files(files) { function download_next(i) { if (i >= files.length) { return; } var a = document.createElement('a'); a.href = files[i].download; a.target = '_parent'; // Use a.download if available, it prevents plugins from opening. if ('download' in a) { a.download = files[i].filename; } // Add a to the doc for click to work. (document.body || document.documentElement).appendChild(a); if (a.click) { a.click(); // The click method is supported by most browsers. } else { $(a).click(); // Backup using jquery } // Delete the temporary link. a.parentNode.removeChild(a); // Download the next file with a small timeout. The timeout is necessary // for IE, which will otherwise only download the first file. setTimeout(function() { download_next(i + 1); }, 500); } // Initiate the first download. download_next(0); } 
   

Il modo più semplice sarebbe quello di servire i file multipli raggruppati in un file ZIP.

Suppongo che potresti avviare più download di file utilizzando un gruppo di iframe o popup, ma dal punto di vista dell’usabilità, un file ZIP è ancora migliore. Chi vuole fare clic su dieci windows di dialogo “Salva con nome” visualizzate dal browser?

Una versione jQuery dell’iframe risponde:

 function download(files) { $.each(files, function(key, value) { $('') .hide() .attr('src', value) .appendTo($('body')) .load(function() { var that = this; setTimeout(function() { $(that).remove(); }, 100); }); }); } 
           
Select File name Downloads
{{tableData.fileName}} download
download selected

{{selectedone}}

app.js var app = angular.module('app', []); app.controller('FirstCtrl', ['$scope','$http', '$filter', function($scope, $http, $filter){ $scope.tableDatas = [ {name: 'value1', fileName:'file1', filePath: 'data/file1.txt', selected: true}, {name: 'value2', fileName:'file2', filePath: 'data/file2.txt', selected: true}, {name: 'value3', fileName:'file3', filePath: 'data/file3.txt', selected: false}, {name: 'value4', fileName:'file4', filePath: 'data/file4.txt', selected: true}, {name: 'value5', fileName:'file5', filePath: 'data/file5.txt', selected: true}, {name: 'value6', fileName:'file6', filePath: 'data/file6.txt', selected: false}, ]; $scope.application = []; $scope.selected = function() { $scope.application = $filter('filter')($scope.tableDatas, { checked: true }); } $scope.downloadAll = function(){ $scope.selectedone = []; angular.forEach($scope.application,function(val){ $scope.selectedone.push(val.name); $scope.id = val.name; angular.element('#'+val.name).closest('tr').find('.downloadable')[0].click(); }); } }]);

esempio di lavoro: https://plnkr.co/edit/XynXRS7c742JPfCA3IpE?p=preview

Sono d’accordo che un file zip è una soluzione più ordinata … Ma se devi spingere più file, ecco la soluzione che ho trovato. Funziona in IE 9 e versioni successive (probabilmente anche versioni inferiori, non l’ho ancora testato), Firefox, Safari e Chrome. Chrome mostrerà un messaggio all’utente per ottenere il suo accordo per scaricare più file la prima volta che il tuo sito lo usa.

 function deleteIframe (iframe) { iframe.remove(); } function createIFrame (fileURL) { var iframe = $(''); iframe[0].src= fileURL; $('body').append(iframe); timeout(deleteIframe, 60000, iframe); } // This function allows to pass parameters to the function in a timeout that are // frozen and that works in IE9 function timeout(func, time) { var args = []; if (arguments.length >2) { args = Array.prototype.slice.call(arguments, 2); } return setTimeout(function(){ return func.apply(null, args); }, time); } // IE will process only the first one if we put no delay var wait = (isIE ? 1000 : 0); for (var i = 0; i < files.length; i++) { timeout(createIFrame, wait*i, files[i]); } 

L'unico effetto collaterale di questa tecnica è che l'utente vedrà un ritardo tra l'invio e la finestra di dialogo di download. Per minimizzare questo effetto, ti suggerisco di utilizzare la tecnica descritta qui e su questa domanda Rileva quando il browser riceve il download del file che consiste nell'impostare un cookie con il tuo file per sapere che è stato avviato il download. Dovrai controllare questo cookie sul lato client e inviarlo sul lato server. Non dimenticare di impostare il percorso corretto per il tuo cookie o potresti non vederlo. Dovrai inoltre adattare la soluzione per il download di più file.

Per migliorare la risposta di @Dmitry Nogin: questo ha funzionato nel mio caso.

Tuttavia, non è testato, poiché non sono sicuro di come il dialogo dei file funzioni su varie combinazioni OS / browser. (Così wiki della comunità.)

  
  

Balance Sheet Year 2014-2015

Sto cercando una soluzione per farlo, ma la decompressione dei file in javascript non era pulita come mi piaceva. Ho deciso di incapsulare i file in un singolo file SVG.

Se hai i file memorizzati sul server (io no), puoi semplicemente impostare href in SVG.

Nel mio caso, convertirò i file in base64 e li incorporo in SVG.

Modifica: SVG ha funzionato molto bene. Se stai per scaricare solo i file, ZIP potrebbe essere migliore. Se stai per visualizzare i file, SVG sembra superiore.

Quando si utilizzano componenti Ajax è ansible avviare più download. Quindi devi usare https://cwiki.apache.org/confluence/display/WICKET/AJAX+update+and+file+download+in+uno+blu

Aggiungi un’istanza di AJAXDownload alla tua Pagina o qualsiasi altra cosa. Creare un AjaxButton e sovrascrivere onSubmit. Creare un AbstractAjaxTimerBehavior e avviare il download.

  button = new AjaxButton("button2") { private static final long serialVersionUID = 1L; @Override protected void onSubmit(AjaxRequestTarget target, Form form) { MultiSitePage.this.info(this); target.add(form); form.add(new AbstractAjaxTimerBehavior(Duration.milliseconds(1)) { @Override protected void onTimer(AjaxRequestTarget target) { download.initiate(target); } }); } 

Buon download!

Sotto il codice funziona al 100%.

Passaggio 1 : incolla sotto il codice nel file index.html

    Angular Test    

Passaggio 2 : incolla sotto il codice nel file index.js

 "use strict"; var x = angular.module('ang', []); x.controller('myController', function ($scope, $http) { var arr = [ {file:"http://localhost/angularProject/w3logo.jpg", fileName: "imageone"}, {file:"http://localhost/angularProject/cv.doc", fileName: "imagetwo"}, {file:"http://localhost/angularProject/91.png", fileName: "imagethree"} ]; $scope.files = function() { angular.forEach(arr, function(val, key) { $http.get(val.file) .then(function onSuccess(response) { console.log('res', response); var link = document.createElement('a'); link.setAttribute('download', val.fileName); link.setAttribute('href', val.file); link.style.display = 'none'; document.body.appendChild(link); link.click(); document.body.removeChild(link); }) .catch(function onError(error) { console.log('error', error); }) }) }; }); 

NOTA : assicurati che tutti e tre i file che stanno per essere scaricati vengano posizionati nella stessa cartella insieme ai file angularProject / index.html o angularProject / index.js .

Funziona su tutti i browser (IE11, firefox, Edge, Chrome e Chrome Mobile) I miei documenti sono in più elementi di selezione. I browser sembrano avere problemi quando si tenta di farlo troppo velocemente … Quindi ho usato un timeout.

 //user clicks a download button to download all selected documents $('#downloadDocumentsButton').click(function () { var interval = 1000; //select elements have class name of "document" $('.document').each(function (index, element) { var doc = $(element).val(); if (doc) { setTimeout(function () { window.location = doc; }, interval * (index + 1)); } }); }); 

Questa è una soluzione che usa le promesse:

  function downloadDocs(docs) { docs[0].then(function (result) { if (result.web) { window.open(result.doc); } else { window.location = result.doc; } if (docs.length > 1) { setTimeout(function () { return downloadDocs(docs.slice(1)); }, 2000); } }); } $('#downloadDocumentsButton').click(function () { var files = []; $('.document').each(function (index, element) { var doc = $(element).val(); var ext = doc.split('.')[doc.split('.').length - 1]; if (doc && $.inArray(ext, docTypes) > -1) { files.unshift(Promise.resolve({ doc: doc, web: false })); } else if (doc && ($.inArray(ext, webTypes) > -1 || ext.includes('?'))) { files.push(Promise.resolve({ doc: doc, web: true })); } }); downloadDocs(files); }); 

Ottenere l’elenco di url con una chiamata ajax e quindi utilizzare il plugin jQuery per scaricare più file paralleli.

  $.ajax({ type: "POST", url: URL, contentType: "application/json; charset=utf-8", dataType: "json", data: data, async: true, cache: false, beforeSend: function () { blockUI("body"); }, complete: function () { unblockUI("body"); }, success: function (data) { //here data --> contains list of urls with comma seperated var listUrls= data.DownloadFilePaths.split(','); listUrls.forEach(function (url) { $.fileDownload(url); }); return false; }, error: function (result) { $('#mdlNoDataExist').modal('show'); } });