Как я могу позволить пользователю загружать несколько файлов при нажатии кнопки?

Итак, у меня есть сервер httpd, на котором есть ссылки на кучу файлов. Допустим, пользователь выбирает три файла из списка файлов для загрузки, и они расположены по адресу:

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

Когда они нажимают кнопку загрузки, я хочу, чтобы они загрузили эти три файла из приведенных выше ссылок.

Моя кнопка загрузки выглядит примерно так:

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

Ответ 1

Лучший способ сделать это - закрепить ваши файлы и ссылку на них:

Другое решение можно найти здесь: Как сделать ссылку открытием нескольких страниц при нажатии

В каком состоянии указано следующее:

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

Сказав это, я все равно поменю на zip файл, так как эта реализация требует JavaScript и иногда также может быть заблокирована как всплывающие окна.

Ответ 2

Это был метод, который работал лучше для меня и не открывал новые вкладки, а просто загружал нужные файлы/изображения:

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

Ответ 3

Вы можете:

  • Заблокируйте выбранные файлы и верните один заархивированный файл.
  • Откройте несколько всплывающих окон, каждый из которых запрашивает загрузку.

Примечание. Вариант 1 объективно лучше.

Edit Найден вариант три: fooobar.com/questions/79075/...

Ответ 4

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


}]);

пример плунжера: https://plnkr.co/edit/XynXRS7c742JPfCA3IpE?p=preview

Ответ 5

Я решил это по-другому, используя window.location. Он работает в Chrome, который, к счастью, является единственным браузером, который мне пришлось поддерживать. Может быть кому-то пригодится. Первоначально я использовал ответ Дэна, который также нуждался в тайм-ауте, который я использовал здесь, или он загружал только один файл.

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

Ответ 6

Вы можете сделать это, создавая события мыши и отправляя их на кнопку. 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);

Ответ 7

Это работает во всех браузерах (IE11, Firefox, Microsoft Edge, Chrome и Chrome Mobile). Мои документы находятся в нескольких выбранных элементах. Браузеры, кажется, имеют проблемы, когда вы пытаетесь сделать это слишком быстро... Поэтому я использовал тайм-аут.

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

Это решение использует обещания:

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

Ответ 8

Мне нравится, что выполнение события click() a элемента внутри for loop for для загрузки нескольких файлов работает только для ограниченного числа файлов (в моем случае 10 файлов). Единственной причиной, которая имела смысл для меня, была скорость выполнения загрузок событий.

Решение, которое работало для меня, заключалось в том, чтобы замедлить выполнение события click(). Я добился этого с помощью исходного кода ниже.

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

Я выполняю событие загрузки click() каждые 300 мс. Когда больше нет файлов для загрузки urls.length == 0 тогда я выполняю clearInterval для функции interval.

Ответ 9

Дэн решение работало на меня до вчерашнего дня. Firefox версии 65 Quantum, похоже, имеет проблемы с несколькими запросами и не допускает многократной загрузки таким способом.