はじめに
ファイル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個ぐらいまでは確認しました)
- サーバー側はエラーのときリダイレクトはしないでください。(リダイレクト先がダウンロードされます。)