Получение XMLHttpRequest Progress из PHP Script - PullRequest
5 голосов
/ 21 октября 2010

Я использую javascript для запуска XMLHttpRequest для PHP-скрипта, который возвращает данные. По сути, я хочу иметь возможность предоставить пользователю индикатор выполнения (вместо вращающегося круга или чего-то еще), который показывает ход получения и получения данных. Я знаю, если бы я получал файл, я мог бы просто проверить заголовок длины содержимого и использовать его, но в случае сценария вы не знаете, сколько данных он получает.

Ответ на этот вопрос может быть таким же простым, как «это невозможно», потому что сейчас это кажется таким. Но в заключение: как вы отслеживаете ход выполнения скрипта (php) и XMLHttpRequest?

Ответы [ 4 ]

2 голосов
/ 28 октября 2010

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

Я написал этот код для определения процента данных, переданных в операции XHR несколько лет назад, поэтому я прошу прощения за то, что он не отражает многолетний опыт кодирования, который я получил с тех пор. Я почти наверняка не написал бы это так сейчас! Тем не менее, мне удалось выловить это, и надеюсь, что это пригодится вам.

В то время, когда это было написано, IE7 была последней доступной версией Explorer, и я помню, что код не работал в этом, следовательно, он содержит код для предотвращения его инициализации в IE. Я никогда не пробовал этот код под версией 8 или бета версией 9, и он действительно может работать в этих версиях, но я не могу ручаться за это. Если вы можете заставить его работать в новой версии IE, пожалуйста, дайте мне знать!

Он работает, выполняя код в beforeSend (обратный вызов, который jQuery предоставляет для кода, который вы хотите запустить перед запуском ajax-запроса), чтобы установить интервал Javascript (в коде я поместил 50 миллисекунд, что, вероятно, слишком часто 200 миллисекунд все равно должно быть достаточно, и нагрузка на систему будет меньше. Каждый раз, когда срабатывает таймер интервала, он запускает функцию, которая просматривает атрибут responseText запроса XHR. Атрибут responseText содержит необработанный текст полученных данных. Подсчитав, сколько символов находится там с помощью строкового метода length (), мы можем определить, сколько байтов уже собрано.

Для определения процента от общего объема данных, которые необходимо отправить, для этого потребуется, чтобы ваш код на стороне сервера отправлял заголовок длины содержимого с точным подсчетом количества байтов, которые он собирается отправить. Это потребует немного сообразительности с вашей стороны, но не должно оказаться слишком сложным. Если вы отправляете точный заголовок длины содержимого, то он используется для расчета процента данных, полученных на данный момент. Если вы не установили заголовок содержимого, то вместо этого отображается объем полученных данных.

<script type="text/javascript">
$.ajax ({
    beforeSend  : function (thisXHR)
    {
        // IE doesn't support responseText access in interactive mode
        if (!$.browser.msie)
        {
            myTrigger = setInterval (function ()
            {
                if (thisXHR.readyState > 2)
                // When there is partial data available use it to determine how much of the document is downloaded
                {   
                    var dlBytes = thisXHR.responseText.length;
                    if (totalBytes == -1)
                        totalBytes  = thisXHR.getResponseHeader ('Content-length');
                    (totalBytes > 0)?
                        $('#progress').html (Math.round ((dlBytes / totalBytes) * 100) + "%"):
                        $('#progress').html (Math.round (dlBytes / 1024) + "K");
                }
            }, 50); // Check the status every 50 miliseconds
        }
    },
    complete    : function ()
    {
        // Kill the download progress polling timer
        if (myTrigger)
            clearInterval (myTrigger);
    }
});
</script>
1 голос
/ 21 октября 2010

С моей головы вы можете использовать 2 ajax-запроса.Один для запуска и ожидания завершения задания, а другой для проверки хода выполнения задания.Я почти уверен, что большинство браузеров могут одновременно выполнять как минимум 2 AJAX-запроса'] с процентом выполнения задания.

У вас есть другой PHP-скрипт (назовем его progress.php), который отображает это значение, т.е.ajax запрос к job.php.У вас есть еще один ajax-запрос к progress.php, который запускается каждые 3 секунды.Вы обновляете свой индикатор выполнения возвращаемым значением.

Вы также можете сделать это с помощью одного ajax-запроса, если запрос к job.php возвращается до завершения задания.Затем вы можете продолжать использовать один ajax-запрос для проверки связи со сценарием progress.php.

0 голосов
/ 22 октября 2010

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

Сохраните где-нибудь на сервере (в базе данных, в файле и т. Д.) Ход выполнения вместе с SID + UID по мере выполнения запроса.1003 *

Используйте второй запрос ajax с таймером для опроса прогресса по SID + UID.

* Возможно, вы можете получить только по UID, но я обнаружил, что он более управляем, когда выможет отслеживать задачи по пользователю / сеансу.

0 голосов
/ 22 октября 2010

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

Кроме того, в некоторых браузерах свойство responseText содержит результаты, возвращаемые до сих пор, и его можно изучить, чтобы получить некоторое представление о прогрессе.

Тем не менее, Internet Explorer (по крайней мере, для IE7, но не уверен, что позже) не поддерживает это, и это ошибка для запроса responseText или responseBody для readyState 3. Я также слышал, что IE вызывает только onreadystatechange один раз с readyState 3, что делает его довольно бесполезным для вашей цели, но я бы посоветовал протестировать его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...