Как получить прогресс от XMLHttpRequest

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

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

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

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
135
0
144 313
7

Ответы 7

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

Если у вас есть доступ к вашей установке apache и вы доверяете стороннему коду, вы можете использовать модуль прогресса загрузки apache (если вы используете apache; есть также модуль прогресса загрузки nginx).

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

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

Для всего загруженного, похоже, нет способа справиться с этим, но есть что-то похожее на то, что вы хотите для загрузки. Когда для параметра readyState установлено значение 3, вы можете периодически запрашивать responseText, чтобы получить весь контент, загруженный в виде String (это не работает в IE), до тех пор, пока все это не станет доступным, после чего он перейдет в состояние readyState 4. Итого байты, загруженные в любой момент времени, будут равны общему количеству байтов в строке, хранящейся в responseText.

Для подхода «все или ничего» к вопросу о загрузке, поскольку вы должны передать строку для загрузки (и можно определить ее общее количество байтов), общее количество байтов, отправленных для readyState 0 и 1, будет равно 0, а общее количество для readyState 2 будет общим количеством байтов в строке, которую вы передали. Общее количество байтов, отправленных и полученных в readyState 3 и 4, будет суммой байтов в исходной строке плюс общее количество байтов в responseText.

Единственный способ сделать это с помощью чистого javascript - реализовать какой-то механизм опроса. Вам нужно будет отправлять запросы ajax через фиксированные интервалы (например, каждые 5 секунд), чтобы получить количество байтов, полученных сервером.

Более эффективным способом было бы использовать вспышку. Гибкий компонент Ссылка на файл периодически отправляет событие «progress», содержащее количество уже загруженных байтов. Если вам нужно придерживаться javascript, существуют мосты между ActionScript и javascript. Хорошая новость в том, что эта работа уже сделана за вас :)

swfupload

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

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

Firefox поддерживает События выполнения загрузки XHR.

Ссылка не работает, и ответ больше ничего не дает.

tforgione 07.03.2021 16:11

Для загруженных байтов это довольно просто. Просто следите за событием 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(); 
}

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

Chris Chilvers 05.09.2012 18:38

@ChrisChilvers Это означает, что файл PHP может быть неправильно рассчитан, верно?

Klaider 20.08.2016 17:25

@nicematt в этом примере было бы хорошо, поскольку он исходит из файла, но если бы вы передавали zip прямо из памяти, вы не могли бы просто составить длину контента или оценить ее.

Chris Chilvers 22.08.2016 11:21

@TheProHands Когда вы посещаете страницу .php, сервер запускает файл PHP и отправляет вам его выход. Сервер должен отправлять длину вывода, а не файл .php.

leewz 11.10.2016 11:40

Может кто-нибудь объяснить, что такое строка «$ ('# progressbar'). Progressbar (« option »,« value », percentComplete);» средства? Это вызывает определенный плагин? Как это работает? Пожалуйста, сделайте ответ понятным для новых пользователей.

Zac 21.06.2017 06:31

@Zac Это просто панель прогресса jQueryUi, показывающая прогресс в пользовательском интерфейсе от 0% до 100%.

albanx 21.06.2017 12:08

@albanx Спасибо. Не могли бы вы указать, какие файлы CSS нужно импортировать для использования этой шкалы? Спасибо

Zac 21.06.2017 20:16

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

Result

Другие вопросы по теме