it-swarm.com.de

Laden Sie mehrere Dateien mit einer einzigen Aktion herunter

Ich bin nicht sicher, ob dies mit Standard-Web-Technologien möglich ist.

Ich möchte, dass der Benutzer in einer einzigen Aktion mehrere Dateien herunterladen kann. Klicken Sie auf die Kontrollkästchen neben den Dateien, und rufen Sie alle Dateien ab, die geprüft wurden.

Ist es möglich - wenn ja, welche grundlegende Strategie empfehlen Sie? Ich weiß, dass ich die Kometen-Technologie verwenden kann, um serverseitige Ereignisse zu erstellen, die eine HttpResponse auslösen. 

86
Ankur

HTTP unterstützt nicht mehr als einen Dateidownload gleichzeitig.

Es gibt zwei Lösungen:

  • Öffnen Sie die x Anzahl der Fenster, um die Dateidownloads zu initiieren (dies würde mit JavaScript erfolgen).
  • bevorzugte LösungErstellen Sie ein Skript, um die Dateien zu komprimieren
47
Jacob Relkin
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);
}
<button onclick="downloadAll(window.links)">Test me!</button>
74
Matěj Pokorný

Sie können einen temporären Satz verborgener Iframes erstellen, den Download über GET oder POST in ihnen initiieren, auf den Start von Downloads warten und Iframes entfernen:

<!DOCTYPE HTML>
<html>
<body>
  <button id="download">Download</button> 

  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
  <script type="text/javascript">

     $('#download').click(function() {
       download('http://nogin.info/cv.doc','http://nogin.info/cv.doc');
     });

     var download = function() {
       for(var i=0; i<arguments.length; i++) {
         var iframe = $('<iframe style="visibility: collapse;"></iframe>');
         $('body').append(iframe);
         var content = iframe[0].contentDocument;
         var form = '<form action="' + arguments[i] + '" method="GET"></form>';
         content.write(form);
         $('form', content).submit();
         setTimeout((function(iframe) {
           return function() { 
             iframe.remove(); 
           }
         })(iframe), 2000);
       }
     }      

  </script>
</body>
</html>

Oder ohne jQuery:

 function download(...urls) {
    urls.forEach(url => {
      let iframe = document.createElement('iframe');
      iframe.style.visibility = 'collapse';
      document.body.append(iframe);

      iframe.contentDocument.write(
        `<form action="${url.replace(/\"/g, '"')}" method="GET"></form>`
      );
      iframe.contentDocument.forms[0].submit();

      setTimeout(() => iframe.remove(), 2000);
    });
  }
49
Dmitry Nogin

Diese Lösung funktioniert in allen Browsern und löst keine Warnungen aus. Anstatt eine iframe zu erstellen, erstellen wir hier für jede Datei einen Link. Dies verhindert, dass Warnmeldungen auftauchen.

Um den Schleifenteil zu handhaben, verwenden wir setTimeout, das für die Arbeit im IE erforderlich ist.

/**
 * 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);
}
<script>
  // Here's a live example that downloads three test text files:
  function do_dl() {
    download_files([
      { download: "http://www.nt.az/reg.txt", filename: "regs.txt" },
      { download: "https://www.w3.org/TR/PNG/iso_8859-1.txt", filename: "standards.txt" },
      { download: "http://qiime.org/_static/Examples/File_Formats/Example_Mapping_File.txt", filename: "example.txt" },
    ]);
  };
</script>
<button onclick="do_dl();">Test downloading 3 text files.</button>

27
speedplane

Am einfachsten ist es, mehrere Dateien in einer Zip-Datei bereitzustellen.

Ich nehme an, Sie könnten mehrere Dateidownloads mit einer Reihe von Iframes oder Popups initiieren, aber aus Sicht der Benutzerfreundlichkeit ist eine Zip-Datei noch besser. Wer möchte durch zehn "Speichern unter" -Dialoge klicken, die der Browser anzeigt?

5
Thilo
        <!doctype html>
    <html ng-app='app'>
        <head>
            <title>
            </title>
            <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
            <link rel="stylesheet" href="style.css">
        </head>
        <body ng-cloack>        
            <div class="container" ng-controller='FirstCtrl'>           
              <table class="table table-bordered table-downloads">
                <thead>
                  <tr>
                    <th>Select</th>
                    <th>File name</th>
                    <th>Downloads</th>
                  </tr>
                </thead>
                <tbody>
                  <tr ng-repeat = 'tableData in tableDatas'>
                    <td>
                        <div class="checkbox">
                          <input type="checkbox" name="{{tableData.name}}" id="{{tableData.name}}" value="{{tableData.name}}" ng-model= 'tableData.checked' ng-change="selected()">
                        </div>
                    </td>
                    <td>{{tableData.fileName}}</td>
                    <td>
                        <a target="_self" id="download-{{tableData.name}}" ng-href="{{tableData.filePath}}" class="btn btn-success pull-right downloadable" download>download</a>
                    </td>
                  </tr>              
                </tbody>
              </table>
                <a class="btn btn-success pull-right" ng-click='downloadAll()'>download selected</a>

                <p>{{selectedone}}</p>
            </div>
            <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
            <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
            <script src="script.js"></script>
        </body>
    </html>


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


}]);

arbeitsbeispiel: https://plnkr.co/edit/XynXRS7c742JPfCA3IpE?p=preview

3
suresh

Eine jQuery-Version des iframe antwortet:

function download(files) {
    $.each(files, function(key, value) {
        $('<iframe></iframe>')
            .hide()
            .attr('src', value)
            .appendTo($('body'))
            .load(function() {
                var that = this;
                setTimeout(function() {
                    $(that).remove();
                }, 100);
            });
    });
}
3

Ich bin damit einverstanden, dass eine Zip-Datei eine ordentlichere Lösung ist ... Aber wenn Sie mehrere Dateien pushen müssen, haben wir hier die Lösung, die ich mir ausgedacht habe. Es funktioniert in IE 9 und höher (möglicherweise auch in einer niedrigeren Version - ich habe es nicht getestet), Firefox, Safari und Chrome. In Chrome wird dem Benutzer eine Nachricht angezeigt, in der er seine Zustimmung zum Herunterladen mehrerer Dateien einholt, wenn er von Ihrer Website zum ersten Mal verwendet wird.

function deleteIframe (iframe) {
    iframe.remove(); 
}
function createIFrame (fileURL) {
    var iframe = $('<iframe style="display:none"></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]);
 }

Der einzige Nebeneffekt dieser Technik ist, dass der Benutzer eine Verzögerung zwischen dem Senden und dem Download-Dialog sieht. Um diesen Effekt zu minimieren, schlage ich vor, dass Sie die Technik beschreiben hier und auf diese Frage Erkennen, wenn der Browser Datei-Download erhält, die darin besteht, ein Cookie mit Ihrer Datei zu setzen, um zu wissen, dass der Download gestartet wurde. Sie müssen dieses Cookie auf der Clientseite prüfen und auf dem Server senden. Vergessen Sie nicht, den richtigen Pfad für Ihr Cookie festzulegen, sonst sehen Sie es möglicherweise nicht. Sie müssen die Lösung auch für den Download mehrerer Dateien anpassen.

2
Melanie

Um @Dmitry Nogins Antwort zu verbessern: Das hat in meinem Fall funktioniert. 

Es wurde jedoch nicht getestet, da ich nicht sicher bin, wie der Dateidialog bei verschiedenen Kombinationen von Betriebssystem und Browser funktioniert. (Also Community-Wiki.)

<script>
$('#download').click(function () {
    download(['http://www.arcelormittal.com/ostrava/doc/cv.doc', 
              'http://www.arcelormittal.com/ostrava/doc/cv.doc']);
});

var download = function (ar) {
    var prevfun=function(){};
    ar.forEach(function(address) {  
        var pp=prevfun;
        var fun=function() {
                var iframe = $('<iframe style="visibility: collapse;"></iframe>');
                $('body').append(iframe);
                var content = iframe[0].contentDocument;
                var form = '<form action="' + address + '" method="POST"></form>';
                content.write(form);
                $(form).submit();
                setTimeout(function() {    
                    $(document).one('mousemove', function() { //<--slightly hacky!
                        iframe.remove();
                        pp();
                    });
                },2000);
        }
        prevfun=fun; 
      });
      prevfun();   
}
</script>
1
Karel Bílek

So mache ich das. Ich öffne mehrere Zip-Dateien, aber auch andere Daten (ich exportiere das Projekt in PDF und gleichzeitig viele ZIPs mit Dokument).

Ich kopiere einfach einen Teil meines Codes. Der Anruf von einer Schaltfläche in einer Liste:

$url_pdf = "pdf.php?id=7";
$url_Zip1 = "Zip.php?id=8";
$url_Zip2 = "Zip.php?id=9";
$btn_pdf = "<a href=\"javascript:;\" onClick=\"return open_multiple('','".$url_pdf.",".$url_Zip1.",".$url_Zip2."');\">\n";
$btn_pdf .= "<img src=\"../../../images/icones/pdf.png\" alt=\"Ver\">\n";
$btn_pdf .= "</a>\n"

Also ein grundlegender Aufruf an eine JS-Routine (Vanilla-Regeln!). Hier ist die JS-Routine:

 function open_multiple(base,url_publication)
 {
     // URL of pages to open are coma separated
     tab_url = url_publication.split(",");
     var nb = tab_url.length;
     // Loop against URL    
     for (var x = 0; x < nb; x++)
     {
        window.open(tab_url[x]);
      }

     // Base is the dest of the caller page as
     // sometimes I need it to refresh
     if (base != "")
      {
        window.location.href  = base;
      }
   }

Der Trick besteht darin, NICHT den direkten Link der Zip-Datei anzugeben, sondern an den Browser zu senden. So was:

  $type_mime = "application/Zip, application/x-compressed-Zip";
 $the_mime = "Content-type: ".$type_mime;
 $tdoc_size = filesize ($the_Zip_path);
 $the_length = "Content-Length: " . $tdoc_size;
 $tdoc_nom = "Pesquisa.Zip";
 $the_content_disposition = "Content-Disposition: attachment; filename=\"".$tdoc_nom."\"";

  header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
  header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");   // Date in the past
  header($the_mime);
  header($the_length);
  header($the_content_disposition);

  // Clear the cache or some "sh..." will be added
  ob_clean();
  flush();
  readfile($the_Zip_path);
  exit();
0
Peter
           <p class="style1">



<a onclick="downloadAll(window.links)">Balance Sheet Year 2014-2015</a>

</p>

<script>
 var links = [
  'pdfs/IMG.pdf',
  'pdfs/IMG_0001.pdf',
 'pdfs/IMG_0002.pdf',
 'pdfs/IMG_0003.pdf',
'pdfs/IMG_0004.pdf',
'pdfs/IMG_0005.pdf',
 'pdfs/IMG_0006.pdf'

];

function downloadAll(urls) {
  var link = document.createElement('a');

  link.setAttribute('download','Balance Sheet Year 2014-2015');
  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);
}
</script>
0
user5598894

Ich suche nach einer Lösung, um dies zu tun, aber das Entpacken der Dateien in Javascript war nicht so sauber, wie ich wollte. Ich entschied mich, die Dateien in einer einzigen SVG-Datei zu kapseln. 

Wenn Sie die Dateien auf dem Server gespeichert haben (kann ich nicht), können Sie die href einfach in der SVG einstellen.

In meinem Fall konvertiere ich die Dateien in base64 und binde sie in das SVG ein.

Edit: Die SVG hat sehr gut funktioniert. Wenn Sie nur die Dateien herunterladen, ist Zip möglicherweise besser. Wenn Sie die Dateien anzeigen, erscheint SVG überlegen.

0
VectorVortec

Unter dem Code 100% arbeiten. 

Schritt 1 : Füge den folgenden Code in index.html ein

<!DOCTYPE html>
<html ng-app="ang">

<head>
    <title>Angular Test</title>
    <meta charset="utf-8" />
</head>

<body>
    <div ng-controller="myController">
        <button ng-click="files()">Download All</button>
    </div>

    <script src="angular.min.js"></script>
    <script src="index.js"></script>
</body>

</html>

Schritt 2 : Fügen Sie den Code in index.js ein

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

NOTE: Stellen Sie sicher, dass alle drei Dateien, die heruntergeladen werden sollen, zusammen mit den Dateien angleProject/index.html oder angleProject/index.js im selben Ordner abgelegt werden.

0
solanki...

Abrufen der Liste der URLs mit ajax-Aufruf und anschließend mit jquery plugin mehrere Dateien parallel herunterladen.

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

    });
0
Ali

Wenn Sie Ajax-Komponenten verwenden, können Sie mehrere Downloads starten. Daher müssen Sie https://cwiki.Apache.org/confluence/display/WICKET/AJAX+update+and+file+download+in+one+blow verwenden.

Fügen Sie Ihrer Seite oder was auch immer eine Instanz von AJAXDownload hinzu. Erstellen Sie einen AjaxButton und überschreiben Sie onSubmit. Erstellen Sie ein AbstractAjaxTimerBehavior und starten Sie den 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);
                }

            });     
        }

Viel Spaß beim Download!

0
stritzi

Dies funktioniert in allen Browsern (IE11, Firefox, Edge, Chrome und Chrome Mobile). Meine Dokumente sind in mehreren Auswahlelementen enthalten. Die Browser scheinen Probleme zu haben, wenn Sie versuchen, dies zu schnell zu tun ... Also habe ich ein Timeout verwendet.

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

Dies ist eine Lösung, die Versprechen verwendet:

 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);
    });
0
Zach Painter