web-dev-qa-db-ja.com

Ajax-ダウンロードする前にファイルのサイズを取得する

基本的に、ファイルサイズの大きさに応じて、AJAXを使用してファイルをダウンロードする必要があるかどうかを判断したいと思います。

この質問は次のように言い換えることもできると思います:ajaxリクエストのヘッダーのみを取得するにはどうすればよいですか?


[〜#〜] edit [〜#〜]ltima-rat コメントで2つの質問がありましたどうやらこれと同じだとすでに聞かれました。それらは非常に似ていますが、どちらもjQueryを必要としています。これに対する非jQueryソリューションが必要です。

19
MiJyn

XHR応答ヘッダーデータを手動で取得できます。

http://www.w3.org/TR/XMLHttpRequest/#the-getresponseheader()-method

この関数は、要求されたURLのファイルサイズを取得します。

function get_filesize(url, callback) {
    var xhr = new XMLHttpRequest();
    xhr.open("HEAD", url, true); // Notice "HEAD" instead of "GET",
                                 //  to get only the header
    xhr.onreadystatechange = function() {
        if (this.readyState == this.DONE) {
            callback(parseInt(xhr.getResponseHeader("Content-Length")));
        }
    };
    xhr.send();
}

get_filesize("http://example.com/foo.exe", function(size) {
    alert("The size of foo.exe is: " + size + " bytes.");
});
29
Hung Doan

HEADはGETとは異なる動作をする可能性があるため、Content-Lengthヘッダーを取得した後にリクエストを中止する次のようなものを提案します。

new Promise(resolve => {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', '/a.bin', true);
    xhr.onreadystatechange = () => {
        resolve(+xhr.getResponseHeader("Content-Length"));
        xhr.abort();
    };
    xhr.send();
}).then(console.log);
2
Ebrahim Byagowi

HEADリクエストが不可能な場合:

Ebrahimの解決策は、Firefoxで中止された要求にcontext-lengthが使用できないため、Firefoxでは機能しませんでした。そのため、「onreadystatechange」イベントの代わりに「onprogress」イベントを使用しました。

new Promise(
  (resolve, reject) => {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.onprogress = (event) => {
      if (event.lengthComputable) {
        resolve(event.total);
      } else {
        reject(new Error('No content-length available'));
      }
      xhr.abort();
    };
    xhr.send();
  }
);

1)ヘッダーのみが必要な場合は、詳細が単純であるが広く知られていないため、「GET」よりも「HEAD」を常に優先する必要があります。回答)、ヘッダーだけでなく、サイズが異なる可能性のある情報の最初のチャンク全体(ヘッダー+本文の一部)をすでに受信していますが、通常、転送サイズは少なくとも不必要に2倍になります。代わりに「HEAD」を使用すると、ヘッダーのみが転送されることを確認できます。

2)Content-Lengthヘッダーは、クライアント側でアクセスできるように、「Access-Control-Expose-Headers」によって公開される必要があります。複数のOriginリソースを処理していて、Content-Lengthが公開されているかどうかわからない場合は、例外を防ぐために、次のように(または他の多くの異なる方法で)イベントハンドラー内で確認できます。

let contentLength = null;

if (checkHeaders(e.target, ['*','Content-Length'])) {
    // YOU CAN ACCESS HEADER
    contentLength = parseInt(e.target.getResponseHeader("Content-Length"));
} else {
    // YOU CAN NOT ACCESS HEADER
    console.log('Content-Length NOT AVAILABLE');
}

function checkHeaders(request, headers) {
    return (headers.some(function (elem) {
        return (request.getResponseHeader("Access-Control-Expose-Headers").includes(elem));
    }));
}

3)Content-LengthヘッダーIS任意のタイプのエンコーディングが適用される場合は禁止されません(一部のコメントで示唆されているように)。ただし、Content-Lengthは通常、デコードされた本文のサイズになることに注意してください。 (そうでない場合でも)これはさまざまな方法で防ぐことができますが、サーバー側の考慮事項です。

0
Ernesto Stifano