14
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-12-08

はじめに

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

参考リンク

14
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?