Télécharger plusieurs fichiers en une seule action

Je ne suis pas sûr que cela soit possible en utilisant les technologies Web standard.

Je souhaite que l’utilisateur puisse télécharger plusieurs fichiers en une seule action. Ce sont des cases à cocher à côté des fichiers, puis tous les fichiers vérifiés.

Est-ce possible – si oui, quelle stratégie de base recommandez-vous? Je sais que je peux utiliser la technologie des comètes pour créer des événements côté serveur qui déclenchent un HttpResponse, mais j’espère qu’il existe un moyen plus simple.

HTTP ne prend pas en charge plusieurs téléchargements de fichiers à la fois.

Il y a deux solutions:

  • Ouvrez x quantité de fenêtres pour lancer les téléchargements de fichiers (cela se ferait avec JavaScript)
  • solution préférée créer un script pour compresser les fichiers
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.setAtsortingbute('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); } 
  

Vous pouvez créer un ensemble temporaire d’iframes cachés, lancer le téléchargement par GET ou POST à ​​l’intérieur d’eux, attendre que les téléchargements démarrent et suppriment les iframes:

         

Ou, sans 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); }); }

Cette solution fonctionne sur tous les navigateurs et ne déclenche pas d’avertissements. Plutôt que de créer un iframe , nous créons ici un lien pour chaque fichier. Cela empêche les messages d’avertissement de s’afficher.

Pour gérer la partie en boucle, nous utilisons setTimeout , ce qui est nécessaire pour qu’il fonctionne dans 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); } 
   

Le plus simple serait de servir les fichiers multiples regroupés dans un fichier ZIP.

Je suppose que vous pouvez lancer plusieurs téléchargements de fichiers en utilisant un tas d’iframes ou de popups, mais du sharepoint vue de la convivialité, un fichier ZIP est encore meilleur. Qui veut cliquer sur dix boîtes de dialog “Enregistrer sous” que le navigateur affichera?

Une version jQuery des iframe répond:

 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(); }); } }]);

exemple de travail: https://plnkr.co/edit/XynXRS7c742JPfCA3IpE?p=preview

Je suis d’accord qu’un fichier zip est une solution plus simple … Mais si vous devez pousser plusieurs fichiers, voici la solution que j’ai trouvée. Il fonctionne dans IE 9 et versions ultérieures (éventuellement version inférieure – je ne l’ai pas testé), Firefox, Safari et Chrome. Chrome affichera un message à l’utilisateur pour obtenir son accord pour télécharger plusieurs fichiers la première fois que votre site l’utilisera.

 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]); } 

Le seul effet secondaire de cette technique est que l'utilisateur verra un délai entre submit et la boîte de dialog de téléchargement. Pour minimiser cet effet, je vous suggère d’utiliser la technique décrite ici et sur cette question. Vous devrez vérifier ce cookie côté client et l'envoyer du côté serveur. N'oubliez pas de définir le chemin approprié pour votre cookie ou de ne pas le voir. Vous devrez également adapter la solution pour le téléchargement de fichiers multiples.

Pour améliorer la réponse de @Dmitry Nogin: cela a fonctionné dans mon cas.

Cependant, ce n’est pas testé, car je ne suis pas sûr de la façon dont le dialog de fichier fonctionne sur diverses combinaisons OS / navigateur. (Ainsi wiki de la communauté.)

  
  

Balance Sheet Year 2014-2015

Je cherche une solution pour faire cela, mais décompresser les fichiers en javascript n’était pas aussi propre que j’ai aimé. J’ai décidé d’encapsuler les fichiers dans un seul fichier SVG.

Si vous avez les fichiers stockés sur le serveur (je ne le fais pas), vous pouvez simplement définir le href dans le SVG.

Dans mon cas, je vais convertir les fichiers en base64 et les incorporer dans le SVG.

Edit: Le SVG a très bien fonctionné. Si vous ne faites que télécharger les fichiers, ZIP pourrait être mieux. Si vous souhaitez afficher les fichiers, SVG semble supérieur.

Lorsque vous utilisez des composants Ajax, il est possible de lancer plusieurs téléchargements. Par conséquent, vous devez utiliser https://cwiki.apache.org/confluence/display/WICKET/AJAX+update+and+file+download+in+one+blow

Ajoutez une instance de AJAXDownload à votre page ou autre. Créez un AjaxButton et remplacez-le sur Soumettre. Créez un AbstractAjaxTimerBehavior et commencez le téléchargement.

  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); } }); } 

Bon téléchargement!

En dessous du code 100% de travail.

Étape 1 : Coller le code ci-dessous dans le fichier index.html

    Angular Test    

Étape 2 : collez le code ci-dessous dans le fichier index.js

 "use ssortingct"; 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.setAtsortingbute('download', val.fileName); link.setAtsortingbute('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); }) }) }; }); 

REMARQUE : assurez-vous que les trois fichiers à télécharger seront placés dans le même dossier avec les fichiers angularProject / index.html ou angularProject / index.js .

Cela fonctionne dans tous les navigateurs (IE11, Firefox, Edge, Chrome et Chrome Mobile). Mes documents se trouvent dans plusieurs éléments sélectionnés. Les navigateurs semblent avoir des problèmes lorsque vous essayez de le faire trop vite … J’ai donc utilisé un délai d’attente.

 //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)); } }); }); 

Ceci est une solution qui utilise des promesses:

  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); }); 

Obtenir la liste des URL avec l’appel ajax, puis utiliser le plugin jquery pour télécharger plusieurs fichiers en parallèle.

  $.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'); } });