web-dev-qa-db-ger.com

Wie kann ein Benutzer mehrere Dateien herunterladen, wenn auf eine Schaltfläche geklickt wird?

Ich habe also einen httpd-Server, der Links zu einer Reihe von Dateien hat. Angenommen, der Benutzer wählt drei Dateien aus einer Dateiliste zum Herunterladen aus, und diese befinden sich unter:

mysite.com/file1 
mysite.com/file2
mysite.com/file3

Wenn sie auf den Download-Button klicken, möchte ich, dass sie diese drei Dateien von den oben genannten Links herunterladen. 

Mein Download-Button sieht ungefähr so ​​aus:

var downloadButton = new Ext.Button({
  text: "Download",
  handler: function(){
    //download the three files here
  }
});
11
Grammin

Der beste Weg, dies zu tun, ist, Ihre Dateien zu komprimieren und darauf zu verlinken:

Die andere Lösung finden Sie hier: Wie kann man einen Link beim Klick auf mehrere Seiten öffnen lassen

Welches besagt folgendes:

HTML:

<a href="#" class="yourlink">Download</a>

JS:

$('a.yourlink').click(function(e) {
    e.preventDefault();
    window.open('mysite.com/file1');
    window.open('mysite.com/file2');
    window.open('mysite.com/file3');
});

Trotzdem würde ich immer noch mit dem Zippen der Datei gehen, da diese Implementierung JavaScript erfordert und manchmal auch als Popups blockiert werden kann.

14
Tanuj

Dies war die Methode, die am besten für mich funktionierte und keine neuen Registerkarten öffnete, sondern nur die benötigten Dateien/Bilder heruntergeladen hat:

var filesForDownload = [];
filesForDownload( { path: "/path/file1.txt", name: "file1.txt" } );
filesForDownload( { path: "/path/file2.jpg", name: "file2.jpg" } );
filesForDownload( { path: "/path/file3.png", name: "file3.png" } );
filesForDownload( { path: "/path/file4.txt", name: "file4.txt" } );

$jq('input.downloadAll').click( function( e )
{
    e.preventDefault();

    var temporaryDownloadLink = document.createElement("a");
    temporaryDownloadLink.style.display = 'none';

    document.body.appendChild( temporaryDownloadLink );

    for( var n = 0; n < filesForDownload.length; n++ )
    {
        var download = filesForDownload[n];
        temporaryDownloadLink.setAttribute( 'href', download.path );
        temporaryDownloadLink.setAttribute( 'download', download.name );

        temporaryDownloadLink.click();
    }

    document.body.removeChild( temporaryDownloadLink );
} );
11
Dan

Du kannst entweder:

  1. Zip die ausgewählten Dateien und geben Sie die eine komprimierte Datei zurück.
  2. Öffnen Sie mehrere Pop-ups, die jeweils zum Herunterladen auffordern.

Hinweis - Option eins ist objektiv besser.

Edit Eine dritte Option gefunden: https://stackoverflow.com/a/9425731/1803682

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


}]);

plunker-Beispiel: https://plnkr.co/edit/XynXRS7c742JPfCA3IpE?p=preview

1
suresh

Ich habe dies anders gelöst, indem ich window.location verwende. Es funktioniert in Chrome, was zum Glück der einzige Browser ist, den ich unterstützen musste. Könnte jemandem nützlich sein. Ursprünglich hatte ich Dans Antwort verwendet, die auch das Timeout benötigte, das ich hier verwendet hatte, oder es wurde nur eine Datei heruntergeladen.

var linkArray = [];
linkArray.Push("http://example.com/downloadablefile1");
linkArray.Push("http://example.com/downloadablefile2");
linkArray.Push("http://example.com/downloadablefile3");    

function (linkArray) {
  for (var i = 0; i < linkArray.length; i++) { 
    setTimeout(function (path) { window.location = path; }, 200 + i * 200, linkArray[i]);
  }        
};
1
Iain M Norman

Sie können dies tun, indem Sie Mausereignisse erstellen und sie an die Schaltfläche senden. Sourse.

hrefList=['mysite.com/1.jpg', 'mysite.com/2.mp4', 'mysite.com/3.gif'];
buttonDownloadAll=document.createElement('a');
buttonDownloadAll.innerText='Download all';
buttonDownloadAll.href='';
buttonDownloadAll.download=false;
downloadFunc=function(){
    buttonDownloadAll.setAttribute('onclick', '');
    buttonDownloadAll.download=true;
    for(var i=0; i<hrefList.length-1; i++){
        buttonDownloadAll.href=hrefList[i];
        var clickEvent = document.createEvent('MouseEvent');
		clickEvent.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); 
        buttonDownloadAll.dispatchEvent(clickEvent);
    }
    buttonDownloadAll.setAttribute('onclick', 'downloadFunc()');
    buttonDownloadAll.download=false;
    buttonDownloadAll.href='';
};
buttonDownloadAll.setAttribute('onclick', 'downloadFunc()');
document.body.appendChild(buttonDownloadAll);

0
PolyGlot

Ich finde, dass das Ausführen des click()-Ereignisses auf dem a-Element innerhalb eines for loop für das Herunterladen mehrerer Dateien nur für eine begrenzte Anzahl von Dateien (in meinem Fall 10 Dateien) funktioniert. Der einzige Grund, der für mich Sinn machte, war das Herunterladen von Ereignissen. 

Die Lösung, die für mich funktionierte, bestand darin, die Ausführung von click() event zu verlangsamen. Ich habe dies mit dem folgenden Quellcode erreicht. 

var urls = [
  'http://example.com/file1',
  'http://example.com/file2',
  'http://example.com/file3'
]

var interval = setInterval(download, 300, urls);

function download(urls) {
  var url = urls.pop();

  var a = document.createElement("a");
  a.setAttribute('href', url);
  a.setAttribute('download', '');
  a.setAttribute('target', '_blank');
  a.click();

  if (urls.length == 0) {
    clearInterval(interval);
  }
}

Ich führe alle 300ms das Downloadereignis click() aus. Wenn keine weiteren Dateien zum Herunterladen von urls.length == 0 vorhanden sind, führe ich clearInterval für die Funktion interval aus.

0
Lukasz Dynowski

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

<select class="document">
    <option val="Word.docx">some Word document</option>
</select>

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

Diese Lösung verwendet Versprechen:

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