Edited at

jsでファイルを一括ダウンロードしてみる


はじめに

ファイル1つ2つをダウンロードするときは、特に問題ないのですが、

数が増えてくると、なかなか面倒になってきます。

通常、こういうときには、サーバー側でファイルをzipなどで1つにまとめて、

ダウンロードすればいいのですが、

今回、日本語のファイル名が文字化けしてしまったため、jsで対応してみました。

(linuxでzipしたものが、windowsで文字化け/そろそろwindowsも問題なくなっているかも?)

当初、簡単に考えていたのですが、


  • jsでリンクを開いても最後のファイルしかダンロードされない。

  • 別タブで開いても動作しない。(そもそもかっこよくない)

などが発生し、ちょっと試行錯誤しましま。


html

ダウンロードのボタンを配置

ダウンロードの<a>タグに


  • ダウンロードのリンクにclassを付与

  • data-download-fileにファイル名を設定

<button id="download_button">一括ダウンロード</button><br>

<a class="download_file" data-download-file="テスト1.xlsx" href="/1/download">ダウンロード</a><br>
<a class="download_file" data-download-file="テスト2.xlsx" href="/2/download">ダウンロード</a><br>
<a class="download_file" data-download-file="テスト3.xlsx" href="/3/download">ダウンロード</a><br>




javascript

jsでは一旦サーバーからブラウザにデータを保持

その後、そのデータをPCに送るようにしています。

実際には、経過を表示する処理などを入れた方がいいです。

    $('#download_button').on('click', function(e){

// 初期化処理
var file_count = $(".download_file").length; // ダウンロード数
var try_count = 0;
var err_file = [];

$('.download_file').each(function() {

var href = $(this).attr('href');
var filename = $(this).data('download-file');

loadFile(href, function (responce) {
// 経過処理
try_count++;
if (responce!=null){
downloadAsFile(filename,responce);
}else{
err_file.push(filename);
}
if (file_count==try_count){
// 終了処理
if (err_file.length!=0){
// エラー処理
}
}
});
});
});

// サーバーからブラウザにロード
var loadFile = function(href, cb) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if (this.readyState == 4 ){
if ( this.status == 200) {
cb(this.response);
}else{
cb(null);
}
}
}
xhr.open('GET', href, true);
xhr.responseType = 'blob';
xhr.send(null);
}

// ブラウザからPCにダウンロード
var downloadAsFile = function(filename, blob) {
var objectURL = window.URL.createObjectURL(blob);
var link = document.createElement("a");
document.body.appendChild(link);
link.href = objectURL;
link.download = filename;
link.click();
document.body.removeChild(link);
};

ファイル名をサーバーから送られたheaderから取得することは可能です。(やってないけど)

if ( this.status == 200) {

var header = this.getResponseHeader('Content-Disposition');
console.log(header);

このあと、headerをattachmentで切り取って、ゴニョゴニョすれば ( 参考まで )


注意事項


  • excelファイルのダウンロードを想定しています。

  • chrome以外で動作確認をしていません。

  • ファイルサイズが大きいときの動作確認をしていません。

  • ファイル数が多いときの動作確認をしていません。(50個ぐらいまでは確認しました)

  • サーバー側はエラーのときリダイレクトはしないでください。(リダイレクト先がダウンロードされます。)


参考リンク