ここで提案されているように、 https://Gist.github.com/HenrikJoreteg/2502497 、jQuery.ajax()
ファイルアップロードに進行中の機能を追加しようとしています。アップロードは正常に機能し、onprogressイベントが発生しますが、期待どおりではありません。ある時間間隔で繰り返し発生するのではなく、アップロードが完了したときに一度だけ発生します。進行中の更新の頻度を指定する方法はありますか?または、できないことをしようとしていますか?ここに私のコードがあります:
$.ajax(
{
async: true,
contentType: file.type,
data: file,
dataType: 'xml',
processData: false,
success: function(xml)
{
// Do stuff with the returned xml
},
type: 'post',
url: '/fileuploader/' + file.name,
xhrFields:
{
onprogress: function(progress)
{
var percentage = Math.floor((progress.total / progress.totalSize) * 100);
console.log('progress', percentage);
if (percentage === 100)
{
console.log('DONE!');
}
}
}
});
短い答え:
いいえ、あなたはxhrFields
を使ってやりたいことをすることはできません。
長答:
XmlHttpRequestオブジェクトには2つの進捗イベントがあります。
応答の進行状況(XmlHttpRequest.onprogress
)
これは、ブラウザがサーバーからデータをダウンロードしているときです。
リクエストの進行状況(XmlHttpRequest.upload.onprogress
)
これは、ブラウザーがサーバーにデータを送信するときです(POSTパラメーター、Cookie、およびファイルを含む)
コードでは応答進行イベントを使用していますが、必要なのは要求進行イベントです。これがあなたのやり方です:
$.ajax({
async: true,
contentType: file.type,
data: file,
dataType: 'xml',
processData: false,
success: function(xml){
// Do stuff with the returned xml
},
type: 'post',
url: '/fileuploader/' + file.name,
xhr: function(){
// get the native XmlHttpRequest object
var xhr = $.ajaxSettings.xhr() ;
// set the onprogress event handler
xhr.upload.onprogress = function(evt){ console.log('progress', evt.loaded/evt.total*100) } ;
// set the onload event handler
xhr.upload.onload = function(){ console.log('DONE!') } ;
// return the customized object
return xhr ;
}
});
xhr
オプションパラメータは、jQueryが使用するネイティブXmlHttpRequestオブジェクトを返す関数でなければなりません。
送信する前に、イベントハンドラーをリクエスト自体に追加する必要があります。 jQuery.ajaxでは、これを「beforeSend」プロパティで許可しています http://api.jquery.com/jQuery.ajax/
例: http://www.dave-bond.com/blog/2010/01/JQuery-ajax-progress-HMTL5/
*編集*そのリンク例の2番目のコードサンプルを確認してください。最初のものはjQueryの最新バージョンでは時代遅れだと思います。
$.ajax({
xhr: function()
{
var xhr = new window.XMLHttpRequest();
//Upload progress
xhr.upload.addEventListener("progress", function(evt){
if (evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
//Do something with upload progress
console.log(percentComplete);
}
}, false);
//Download progress
xhr.addEventListener("progress", function(evt){
if (evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
//Do something with download progress
console.log(percentComplete);
}
}, false);
return xhr;
},
type: 'POST',
url: "/",
data: {},
success: function(data){
//Do something success-ish
}
});
これは、Stack Overflowの別の場所での別の答えのハックですが、あなたの質問には答えていると思います。サーバーからスクロール可能なdivに「ストリーム化された」データをポンピングする独自のニーズに合わせて修正しました(これにより、常に最後までスクロールし、時間の経過とともに進行し、レコードセット全体が完了するのを待たずに済みます) 。
クライアント側以下のコードは、結果のコンテンツをID「scrollable_area」(その後スクロール可能)で事前定義されたdivに追加します...
<div style="position:absolute; left:5px; right:5px; top:5px; height:35px;">
<label for="auto_scroll">Auto Scroll</label> <input type="checkbox" id="auto_scroll" checked>
</div>
<div id="scrollable_area" style="position:absolute; overflow:auto; left:5px; right:5px; top:45px; bottom:5px;"></div>
<script type="text/javascript">
var last_response_len = false;
var auto_scroll = null;
var scrollable_area = null;
$().ready(function() {
auto_scroll = document.getElementById("auto_scroll");
scrollable_area = document.getElementById("scrollable_area");
$.ajax("your_api_call.php", {
xhrFields: {
onprogress: function(e) {
var this_response, response = e.currentTarget.response;
if(last_response_len === false) {
this_response = response;
last_response_len = response.length;
} else {
this_response = response.substring(last_response_len);
last_response_len = response.length;
}
scrollable_area.innerHTML += this_response;
if(auto_scroll.checked) {
scrollable_area.scrollTop = scrollable_area.clientHeight + scrollable_area.scrollHeight + 500;
}
}
}
})
.done(function(data) {
console.log("Completed response");
})
.fail(function(data) {
console.log("Error: ", data);
});
console.log("your_api_call.php Request Sent!");
});
</script>
サーバー側 "your_api_call.php"ファイル呼び出しは、出力を(データ行ごとに)フラッシュする必要があり、その後、上記の "scrollable_area" div内にすぐに表示できます。 ..
// Do Db loop
while ($record = $recordset->fetch(PDO::FETCH_ASSOC)) {
set_time_limit(10); // Don't timeout on large data sets seeing as this is a big task that we are wanting to watch progress!
echo 'Do what you gotta do... ' . $record["register_id"] . '<br>';
flush(); // Push to the client / ajax
ob_flush(); // As above
}
短い答え...はい。お役に立てれば :-)