2008-09-16 2 views
115

Возможно ли получить прогресс XMLHttpRequest (загруженные байты, загруженные байты)?Как получить прогресс от XMLHttpRequest

Было бы полезно показать индикатор выполнения, когда пользователь загружает большой файл. Стандартный API, похоже, не поддерживает его, но может быть, есть какое-то нестандартное расширение в любом из браузеров? Похоже, что это довольно очевидная функция, поскольку клиент знает, сколько байтов было загружено/загружено.

примечание: я знаю о «опросе сервера для прогресса» (это то, что я делаю прямо сейчас). основная проблема с этим (кроме сложного серверного кода) заключается в том, что обычно при загрузке большого файла соединение пользователя полностью закрывается, потому что большинство интернет-провайдеров предлагают плохой поток вверх. Поэтому делать дополнительные запросы не так отзывчивы, как я надеялся. Я надеялся, что есть способ (может быть, нестандартный), чтобы получить эту информацию, которую браузер всегда имеет.

ответ

10

Там хорошая дискуссия индикатора прогресса для AJAX шаблона здесь:

http://ajaxpatterns.org/Progress_Indicator

Одним из наиболее перспективных подходов, как представляется, открытие второго канала связи обратно на сервер, чтобы спросить его, сколько передача завершена.

+7

Я думаю, что ссылка может быть мертвым – 2016-07-10 21:12:22

2

Если у вас есть доступ к вашему программному обеспечению apache и доверяют стороннему коду, вы можете использовать apache upload progress module (если вы используете apache, есть также nginx upload progress module).

В противном случае вам нужно будет написать сценарий, который вы можете ударить вне диапазона, чтобы запросить статус файла (например, проверка размера файла tmp).

В Firefox 3 есть некоторая работа. Я полагаю, что добавить браузер для поддержки загрузки в браузере, но это не будет входить во все браузеры и быть широко принятым на некоторое время (больше жаль).

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

Эта библиотека позволяет зарегистрировать яваскрипта обработчик на событие прогресса вспышки.

Это решение обладает преимуществом, не требующим дополнительных ресурсов на стороне сервера.

122

Для загруженных байтов это довольно просто. Просто просмотрите событие xhr.upload.onprogress. Браузер знает размер файлов, которые он должен загрузить, и размер загруженных данных, поэтому он может предоставить информацию о ходе.

Для загруженных байтов (при получении информации с помощью xhr.responseText) это немного сложнее, поскольку браузер не знает, сколько байтов будет отправлено в запросе сервера. Единственное, что браузер знает в этом случае, это размер байтов, которые он получает.

Существует решение для этого, достаточно установить заголовок Content-Length на сценарии сервера, чтобы получить общий размер байтов, который будет получать браузер.

Подробнее перейти к https://developer.mozilla.org/en/Using_XMLHttpRequest.

Пример: Мой сценарий сервер читает файл почтового индекса (он занимает 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

Стоит отметить, «Content-Length» не оценивается длина, она должна быть точной длина слишком короткая, и браузер отключит загрузку слишком долго, и браузер предположит, что загрузка не завершена. – 2012-09-05 14:38:37

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