九保すこひです(フリーランスのITコンサルタント、エンジニア)
さてさて、ここのところLaravelやTwilioの話題ばかりでJavaScriptがメインになる記事をお届けできていませんでした。
そして、ちょうどというか偶然というかひとつJavaScriptである機能をつくることがあったので、今回はそのテクニックをご紹介したいと思います。
その内容とは・・・
Ajaxで複数ファイルをダウンロードさせる方法
です。
例えば、JavaScriptで1つファイルをダウンロードさせるには、以下のように強制的にリダイレクトしてやればOKです。
location.href = '(ダウンロードするURL)';
しかも、移動先がダウンロード用のヘッダーを送信していれば実際にはページ移動することなくダウンロードだけできるようになります。
ただし、この場合1つだけ制限があって、「たった1つのファイルだけしかダウンロードできない」んです。
つまり、例えば「検索結果として表示されているデータの中からいくつか選択し、それらに関連する全ファイルをダウンロードする」といった場合にはlocation.hrefは使えないということになります。
そこで!
今回はこの「複数ダウンロード」を実現するテクニックをAjaxを使って実装してみたいと思います。
ぜひ皆さんのお役に立てると嬉しいです😊✨

実行環境: axios 0.19(ダウンロードテスト環境としてLaravel 6.x)
目次
テキストファイルをダウンロードできるようにする
まずはテストとして、Laravelで「アクセスするとテキストファイルがダウンロードできる」URLをつくります。
※ 不要の場合は次がメインのコードになりますのでそちらまで読み飛ばしてください。
routes/web.phpを開いて以下のコードを追加してください。
Route::get('test_download/{number}', function($number){
return response()->streamDownload(function() use($number) {
echo $number .'番目のテキストファイルです。';
}, 'test.txt');
});
これで、/test/download/(数字)にアクセスするとテキストファイルがダウンロードされることになります。
※ 今回はテストですので、ルートの中で全て完結するコードにしますが、本番環境ではきちんとコントローラーをつくることをおすすめします。
Ajaxで複数ファイルをダウンロードする(ES6バージョン)
では、ここからがメインのコードになりますが、ここではES6(アロー関数などの新しいJavaScript)の書き方になっています。
そのため、IE 11もサポートしたい場合は次の「Ajaxで複数ファイルをダウンロードする(IE 11もOKバージョン)」をご覧ください。
<html>
<body>
<div>
<button type="button" onclick="onClick()">ダウンロードする</button>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.min.js"></script>
<script>
function onClick() {
for(let i = 1 ; i <= 3 ; i++) { // 3ファイルをダウンロード
let filename = 'test_text_'+ i +'.txt';
axios({
url: '/test_download/'+ i,
method: 'get',
responseType: 'blob',
})
.then(response => {
const blob = new Blob([response.data]);
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.setAttribute('download', filename);
document.body.appendChild(link);
link.click();
})
.catch(error => {
// エラー処理
});
}
}
</script>
</body>
</html>
この中では、まず以下のようなボタンをつくります。
![]()
そして、このボタンがクリックされたときに実行されるのがonClick()で、この中ではfor()で3回ループするようにし、その度にaxiosを使ってダウンロードURLにアクセスすることになります。
通常のaxiosのAjaxだとシンプルに以下のようにしますが、今回はresponseTypeにblobを指定していることに注目してください。(つまり、バイナリデータとして処理しています)
axios.get(url)
.then(response => {
// ここで何かを実行
});
そして、then()内ではダウンロードURLから取得したレスポンス・データからblobインスタンスをつくり、<a>タグをつくってhrefに作成したblobデータをセットしています。
さらに、この<a>タグにはHTML 5のdownload属性をつけて、クリックされるとページ移動ではなく、ダウンロードが実行されるようになります。(つまり、このタグは以下のようになります)
<a href="blob:http://******" download="test_text_1.txt"></a>
そして最終的にこの<a>タグを<body>タグに追加し、click()メソッドを実行することで自動的に「クリックしたもの」として処理をさせています。
Ajaxで複数ファイルをダウンロードする(IE 11もOKバージョン)
先ほどのコードはES6を使った比較的新しいJavaScriptのコードの書き方でしたが、残念ながら(よくあることですが😫)IE 11では動きません。
そのため、この項目ではIE 11にも対応したコードをご紹介します。
<html>
<body>
<div>
<button type="button" onclick="onClick()">ダウンロードする</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.min.js"></script>
<script>
function onClick() {
for(let i = 1 ; i <= 3 ; i++) { // 3ファイルをダウンロード
let filename = 'test_text_'+ i +'.txt';
axios({
url: '/test_download/'+ i,
method: 'get',
responseType: 'blob',
})
.then(function(response) {
const blob = new Blob([response.data]);
if(typeof window.navigator.msSaveBlob !== 'undefined') { // IE 11
window.navigator.msSaveBlob(blob, filename);
} else {
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.setAttribute('download', filename);
document.body.appendChild(link);
link.click();
}
})
.catch(function() {
// エラー処理
});
}
}
</script>
</body>
</html>
ES6バージョンと違う部分は、3つです。
まず、基本的なことですがIE 11ではアロー関数は使えませんので全て旧式のfunction(){ *** }という書き方に変更しています。
そして2つ目は、axios(Ajax用のパッケージ)ですが、これもIE 11ではそのままでは動きません。(Promiseが原因のようです)
そのため、IE 11でaxiosが使えるようにするために以下のcdnを読み込んでいます。
<script src="https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js"></script>
そして最後に、<a>タグのdownload要素もIE 11では使えないため、代わりにmsSaveBlobを使っています。(というか、これがあるならdownloadのエイリアス的にしてくれればいいのに・・・という気はしなくもありません😂)
window.navigator.msSaveBlob(blob, filename);
ダウンロードする
実際に今回開発したソースコードを以下からダウンロードすることができます。(ES6バージョン、IE 11もOKバージョンの両方が入っています)
※ ただし、ダウンロードするURLはご自身で用意してください。
Ajaxで複数ファイルをダウンロードさせるおわりに
ということで今回はAjaxを使って一気に複数ファイルをダウンロードさせる方法をご紹介しました。
この方法を使えば、いちいち一個ずつボタンをクリックしてダウンロードしなくてもよくなるので、ユーザビリティの向上にもつながるかと思います。
なお、JavaScriptを使って複数のファイルを「Zip化」してダウンロードするzip.jsというライブラリもあったりしますので、こちらも活用してみるのもいいかもしれません。
ぜひ皆さんの開発でも使ってみてくださいね。
ではでは〜😊✨






