web-dev-qa-db-ja.com

ボタンがクリックされたときにユーザーに複数のファイルをダウンロードさせるにはどうすればよいですか?

そのため、多数のファイルへのリンクを持つhttpdサーバーを実行しています。ユーザーがダウンロードするファイルリストから3つのファイルを選択し、それらが次の場所にあるとします。

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

ダウンロードボタンをクリックすると、上記のリンクからこれら3つのファイルをダウンロードするようになります。

ダウンロードボタンは次のようになります。

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

これを行うための最良の方法は、ファイルを圧縮し、それにリンクすることです。

他の解決策はここにあります: リンクをクリックして複数のページを開く方法

次のように述べています:

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

このことを言っても、この実装にはJavaScriptが必要であり、ポップアップとしてブロックされることもあるため、ファイルの圧縮を続けます。

16
Tanuj

これは私にとって最適な方法であり、新しいタブを開かず、必要なファイル/画像をダウンロードしただけでした:

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

次のいずれかを実行できます。

  1. 選択したファイルを圧縮し、圧縮した1つのファイルを返します。
  2. それぞれダウンロードを促す複数のポップアップを開きます。

注-オプション1は客観的に優れています。

Editオプション3を見つけました: 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();
    });
}         


}]);

プランカーの例: https://plnkr.co/edit/XynXRS7c742JPfCA3IpE?p=preview

1
suresh

Window.locationを使用して、これを別の方法で解決しました。 Chromeで動作します。Chromeは幸いなことに、サポートする必要がある唯一のブラウザです。誰かに役立つかもしれません。私は最初にダンの答えを使用しましたが、これにはここで使用したタイムアウトも必要でした。または、ファイルを1つだけダウンロードしました。

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

複数のファイルをダウンロードするために_for loop_内のa要素でclick()イベントを実行すると、限られた数のファイル(私の場合は10個のファイル)でしか動作しません。私にとって意味のあるこの動作を説明する唯一の理由は、click()イベントによって実行されるダウンロードの速度/間隔です。

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を実行してダウンロードを停止します。

1
Lukasz Dynowski

これはすべてのブラウザー(IE11、Firefox、Microsoft Edge、ChromeおよびChromeモバイル)で動作します。私のドキュメントには複数の選択要素があります。あなたがそれをあまりにも速くしようとするとき...だから私はタイムアウトを使用しました。

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

それを行うには、マウスイベントを作成し、ボタンにディスパッチします。 ソース

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