web-dev-qa-db-ja.com

XHR2 / AJAXを使用してファイルをダウンロードするための進行状況バーを表示する

Ajaxを使用してファイルをダウンロードし、カスタムダウンロードプログレスバーを表示しようとしています。

問題は、その方法を理解できないことです。進行状況を記録するコードを書きましたが、ダウンロードを開始する方法がわかりません。

注:ファイルはさまざまなタイプです。

前もって感謝します。

[〜#〜] js [〜#〜]

// Downloading of files
filelist.on('click', '.download_link', function(e){
    e.preventDefault();
    var id = $(this).data('id');
    $(this).parent().addClass("download_start");

    $.ajax({
        xhr: function () {
            var xhr = new window.XMLHttpRequest();
            // Handle Download Progress
            xhr.addEventListener("progress", function (evt) {
                if(evt.lengthComputable) {
                    var percentComplete = evt.loaded / evt.total;
                    console.log(percentComplete);
                }
            }, false);
            return xhr;
        },
        complete: function () {
            console.log("Request finished");
        }
    })
});

HTMLおよびPHP

    <li>
    <div class="f_icon"><img src="' . $ico_path . '"></div>
    <div class="left_wing">
       <div class="progressbar"></div>
       <a class="download_link" href="#" id="'.$file_id.'"><div class="f_name">' . $full_file_name . '</div></a>
       <div class="f_time_size">' . date("M d, Y", $file_upload_time) . '&nbsp; &#149; &nbsp;' . human_filesize($file_size) . '</div>
    </div>

    <div class="right_wing">
       <div class="f_delete">
       <a class="btn btn-danger" href="#" aria-label="Delete" data-id="'.$file_id.'" data-filename="'.$full_file_name.'"><i class="fa fa-trash-o fa-lg" aria-hidden="true" title="Delete this?"></i>
       </a>
    </div>
   </div>
    </li>
11
Ayan

ユーザーにダウンロードプロセスの進行状況バーを表示する場合は、xmlhttprequest内でダウンロードする必要があります。ここでの問題の1つは、ファイルが大きい場合-ブラウザがディスクに書き込む前にブラウザのメモリ内に保存されることです(通常のダウンロードファイルを使用する場合は直接保存されます)ディスクに保存すると、大きなファイルに大量のメモリが保存されます)。

別の重要な注意事項-lengthComputableがtrueになるためには、サーバーはContent-Lengthヘッダーとファイルのサイズ。

JavaScriptコードは次のとおりです。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="a1" data-filename="filename.xml">Click to download</div>
<script>
$('#a1').click(function() {
    var that = this;
    var page_url = 'download.php';

    var req = new XMLHttpRequest();
    req.open("POST", page_url, true);
    req.addEventListener("progress", function (evt) {
        if(evt.lengthComputable) {
            var percentComplete = evt.loaded / evt.total;
            console.log(percentComplete);
        }
    }, false);

    req.responseType = "blob";
    req.onreadystatechange = function () {
        if (req.readyState === 4 && req.status === 200) {
            var filename = $(that).data('filename');
            if (typeof window.chrome !== 'undefined') {
                // Chrome version
                var link = document.createElement('a');
                link.href = window.URL.createObjectURL(req.response);
                link.download = filename;
                link.click();
            } else if (typeof window.navigator.msSaveBlob !== 'undefined') {
                // IE version
                var blob = new Blob([req.response], { type: 'application/force-download' });
                window.navigator.msSaveBlob(blob, filename);
            } else {
                // Firefox version
                var file = new File([req.response], filename, { type: 'application/force-download' });
                window.open(URL.createObjectURL(file));
            }
        }
    };
    req.send();
});
</script>

また、使用できるphpコードの例を次に示します。

<?php
$filename = "some-big-file";
$filesize = filesize($filename);

header("Content-Transfer-Encoding: Binary");
header("Content-Length:". $filesize);
header("Content-Disposition: attachment");

$handle = fopen($filename, "rb");
if (FALSE === $handle) {
    exit("Failed to open stream to URL");
}

while (!feof($handle)) {
    echo fread($handle, 1024*1024*10);
    sleep(3);
}

fclose($handle);

Localhostでのテストのために低速接続をシミュレートするためにスリープを追加したことに注意してください。
あなたは削除する本番環境で:)

20
Dekel