2008-09-16 12 views
115

XMLHttpRequest(アップロードされたバイト数、ダウンロードされたバイト数)の進捗状況を取得できますか?XMLHttpRequestからの進捗状況

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

注:私は「進歩のためにサーバーをポーリングする」という選択肢を知っています(これは私が今やっていることです)。 (複雑なサーバー側コード以外の)主な問題は、大部分のファイルがアップロードされている間は、ほとんどのISPが貧弱なアップストリームを提供するため、ユーザーの接続が完全に閉鎖されていることです。余分な要求をすることは、私が望むほど反応しません。私はブラウザが常に持っているこの情報を得るための方法(おそらく非標準的)があることを望んでいました。

答えて

10

ここAJAXパターンの進捗インジケータの素敵な議論があります:

http://ajaxpatterns.org/Progress_Indicator

最も有望なアプローチの一つは、どのように多くのことを尋ねるために戻ってサーバに第2の通信チャネルを開いているように見えます転送が完了しました。

+7

私はリンクが注目に値する –

2

Apacheのインストールと信頼できる第三者コードにアクセスできる場合は、apache upload progress moduleを使用できます(Apacheを使用している場合は、nginx upload progress moduleもあります)。

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

Firefoxで進行中の作業がいくつかあります。私は、アップロードの進捗状況のサポートをブラウザに追加すると信じていますが、それはすべてのブラウザに入り込むことはなく、しばらくの間広く採用されることでしょう(もっと残念です)。

4

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

アップロードの質問には全く何もしないアプローチのために、アップロードのための文字列を渡す必要があるため(その合計バイトを判断することができます)、readyState 0と1のために送信される合計バイト数は0になります。 readyState 2の合計は、渡した文字列の合計バイト数になります。readyState 3と4で送受信された合計バイト数は、元の文字列のバイトとresponseTextの合計バイトの合計になります。

-6

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

もっと効率的な方法は、フラッシュを使用することです。 flexコンポーネントFileReferenceは、すでにアップロードされたバイト数を保持する 'progress'イベントを定期的に送出します。 javascriptを使用する必要がある場合は、actionscriptとjavascriptの間でブリッジを使用できます。 良いニュースは、この作業はすでにあなたのために行われているということです:)

swfupload

このライブラリは、フラッシュprogressイベントのjavascriptのハンドラを登録することができます。

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

122

アップロードされたバイトは非常に簡単です。 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(); 
} 
+24

死んだかもしれないと思う、「コンテンツ長は」推定長さではない、それは正確でなければなら長さが短すぎるとブラウザがダウンロードを途切れさせてしまい、ブラウザはダウンロードが完了しなかったとみなします。 –

+1

はい、正解が間違っている、混乱しているだけです – albanx

+0

@ChrisChilversつまり、PHPファイルが正しく計算されない可能性があります。 – Hydro

2

<!DOCTYPE html> 
 
<html> 
 
<body> 
 
<p id="demo">result</p> 
 
<button type="button" onclick="get_post_ajax();">Change Content</button> 
 
<script type="text/javascript"> 
 
\t function update_progress(e) 
 
\t { 
 
\t if (e.lengthComputable) 
 
\t { 
 
\t  var percentage = Math.round((e.loaded/e.total)*100); 
 
\t  console.log("percent " + percentage + '%'); 
 
\t } 
 
\t else 
 
\t { 
 
\t \t console.log("Unable to compute progress information since the total size is unknown"); 
 
\t } 
 
\t } 
 
\t function transfer_complete(e){console.log("The transfer is complete.");} 
 
\t function transfer_failed(e){console.log("An error occurred while transferring the file.");} 
 
\t function transfer_canceled(e){console.log("The transfer has been canceled by the user.");} 
 
\t function get_post_ajax() 
 
\t { 
 
\t \t var xhttp; 
 
\t \t if (window.XMLHttpRequest){xhttp = new XMLHttpRequest();}//code for modern browsers} 
 
\t \t else{xhttp = new ActiveXObject("Microsoft.XMLHTTP");}// code for IE6, IE5 \t \t 
 
\t \t xhttp.onprogress = update_progress; 
 
\t \t xhttp.addEventListener("load", transfer_complete, false); 
 
\t \t xhttp.addEventListener("error", transfer_failed, false); 
 
\t \t xhttp.addEventListener("abort", transfer_canceled, false); \t \t 
 
\t \t xhttp.onreadystatechange = function() 
 
\t \t { 
 
\t  \t if (xhttp.readyState == 4 && xhttp.status == 200) 
 
\t  \t { 
 
\t  \t \t document.getElementById("demo").innerHTML = xhttp.responseText; 
 
\t  \t } 
 
\t \t }; 
 
\t xhttp.open("GET", "http://it-tu.com/ajax_test.php", true); 
 
\t xhttp.send(); 
 
\t } 
 
</script> 
 
</body> 
 
</html>

Result

関連する問題