137

XMLHttpRequestの進行状況(アップロードされたバイト数、ダウンロードされたバイト数)を取得することは可能ですか?

これは、ユーザーが大きなファイルをアップロードしているときに進行状況バーを表示するのに役立ちます。標準のAPIはそれをサポートしていないようですが、ブラウザのいずれかに非標準の拡張機能があるのではないでしょうか。クライアントはアップロード/ダウンロードされたバイト数を知っているので、結局のところ、それはかなり明白な機能のようです。

注:「サーバーをポーリングして進行状況を確認する」という代替案を認識しています(これが現在行っていることです)。これに関する主な問題(複雑なサーバー側コードを除く)は、通常、大きなファイルをアップロードしている間、ほとんどのISPが貧弱なアップストリームを提供するため、ユーザーの接続が完全に停止することです。したがって、追加のリクエストを行うことは、私が望んでいたほど応答性が高くありません。私は、ブラウザが常に持っているこの情報を取得する方法(おそらく非標準)があることを望んでいました。

4

7 に答える 7

139

アップロードされたバイトの場合、それは非常に簡単です。xhr.upload.onprogressイベントを監視するだけです。ブラウザは、アップロードする必要があるファイルのサイズとアップロードされたデータのサイズを認識しているため、進行状況情報を提供できます。

ダウンロードされたバイトの場合 ( で情報を取得する場合xhr.responseText)、ブラウザはサーバー要求で送信されるバイト数がわからないため、少し難しくなります。この場合、ブラウザが認識しているのは、受信しているバイトのサイズだけです。

Content-Lengthこれには解決策があります。ブラウザが受信するバイトの合計サイズを取得するには、サーバー スクリプトにヘッダーを設定するだけで十分です。

詳細については、https://developer.mozilla.org/en/Using_XMLHttpRequestにアクセスしてください。

例: 私のサーバー スクリプトは zip ファイルを読み取ります (5 秒かかります):

$filesize=filesize('test.zip');

header("Content-Length: " . $filesize); // set header length
// if the headers is not set then the evt.loaded will be 0
readfile('test.zip');
exit 0;

これで、サーバー スクリプトのダウンロード プロセスを監視できます。これは、全体の長さがわかっているためです。

function updateProgress(evt) 
{
   if (evt.lengthComputable) 
   {  // evt.loaded the bytes the browser received
      // evt.total the total bytes set by the header
      // jQuery UI progress bar to show the progress on screen
     var percentComplete = (evt.loaded / evt.total) * 100;  
     $('#progressbar').progressbar( "option", "value", percentComplete );
   } 
}   
function sendreq(evt) 
{  
    var req = new XMLHttpRequest(); 
    $('#progressbar').progressbar();    
    req.onprogress = updateProgress;
    req.open('GET', 'test.php', true);  
    req.onreadystatechange = function (aEvt) {  
        if (req.readyState == 4) 
        {  
             //run any callback here
        }  
    };  
    req.send(); 
}
于 2010-09-12T10:03:26.047 に答える
11

Firefox は、XHR ダウンロード進行状況イベントをサポートしています。

編集 2021-07-08 10:30 PDT

上記のリンクは死んでいます。Mozilla WebDev サイトで検索すると、次のリンクが見つかりました。

https://developer.mozilla.org/en-US/docs/Web/API/ProgressEvent

XMLHttpRequest で progress イベントを使用する方法を説明し、例を示します。以下に例を示します。

var progressBar = document.getElementById("p"),
    client = new XMLHttpRequest()
client.open("GET", "magical-unicorns")
client.onprogress = function(pe) {
  if(pe.lengthComputable) {
    progressBar.max = pe.total
    progressBar.value = pe.loaded
  }
}
client.onloadend = function(pe) {
  progressBar.value = pe.loaded
}
client.send()

また、このリンクも見つけました。これは、元のリンクが指していると思います。

https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/progress_event

于 2010-07-29T08:18:12.600 に答える
7

最も有望なアプローチの 1 つは、サーバーに 2 番目の通信チャネルを開き、転送がどの程度完了したかをサーバーに尋ねることです。

于 2008-09-16T21:04:06.877 に答える
5

アップロードされた合計については、それを処理する方法はないようですが、ダウンロードしたいものに似たものがあります。readyStateが3になると、responseTextに定期的にクエリを実行して、Stringまでダウンロードされたすべてのコンテンツを取得できます(これはIEでは機能しません)。すべてが使用可能になると、readyState4に移行します。任意の時点でダウンロードされるバイトは、responseTextに格納されている文字列の合計バイトに等しくなります。

アップロードの質問に対するオールオアナッシングアプローチの場合、アップロードのために文字列を渡す必要があるため(そして、その合計バイト数を決定することが可能です)、readyState 0および1に送信される合計バイト数は0になり、readyStateの合計は0になります。 2は、渡した文字列の合計バイト数になります。readyState3および4で送受信された合計バイト数は、元の文字列のバイト数とresponseTextの合計バイト数の合計になります。

于 2008-09-16T21:11:37.657 に答える
2

apacheのインストールにアクセスでき、サードパーティのコードを信頼している場合は、apacheのアップロードの進行状況モジュールを使用できます(apacheを使用している場合は、nginxのアップロードの進行状況モジュールもあります)。

それ以外の場合は、ファイルのステータスを要求するために帯域外でヒットできるスクリプトを作成する必要があります(たとえば、tmpファイルのファイルサイズを確認します)。

Firefox 3で進行中の作業がいくつかありますが、アップロードの進行状況のサポートをブラウザーに追加すると思いますが、それがすべてのブラウザーに適用され、しばらくの間広く採用されるわけではありません(残念です)。

于 2008-09-16T21:06:53.580 に答える
-7

純粋な JavaScript でこれを行う唯一の方法は、ある種のポーリング メカニズムを実装することです。サーバーが受信したバイト数を取得するには、一定の間隔 (たとえば 5 秒ごと) で ajax リクエストを送信する必要があります。

より効率的な方法は、フラッシュを使用することです。Flex コンポーネントのFileReferenceは、アップロード済みのバイト数を保持する「progress」イベントを定期的に送出します。JavaScript を使い続ける必要がある場合は、actionscript と JavaScript の間でブリッジを使用できます。良いニュースは、この作業はすでに完了していることです:)

swfupload

このライブラリを使用すると、フラッシュ進行イベントに JavaScript ハンドラを登録できます。

このソリューションには、サーバー側で追加のリソースを必要としないという大きな利点があります。

于 2008-09-16T21:24:02.773 に答える