javascript — источник события — & gt; Сервер возвращает поток событий навалом, а не возвратом в чанк

У меня есть PHP-скрипт, который импортирует большие данные из CSV-файлов с проверками.
Для этого мне нужно показать прогресс пользователю. Я использовал Event Streaming для этого.
Когда я что-то повторяю, я хочу, чтобы это передавалось клиенту один за другим вместо того, чтобы сервер отправлял весь вывод навалом.
Я уже поиграл с ob_start (), ob_implicit_flush () & ob_flush (), но они не работают.
Мой скрипт отлично работает на другом сервере.
Ниже приведены конфигурации сервера:

Конфигурация сервера, на которой код не отвечает должным образом, т.е.

ОС: Linux
Версия PHP 5.4.36-0 + deb7u3
Серверный API: CGI / FastCGI
Ограничение памяти: 128М
output_buffering: нет значения

Как я уже сказал, код работает должным образом на другом сервере, который имеет почти такую ​​же конфигурацию, т.е.

ОС: Linux
Версия PHP 5.4.37
Серверный API: CGI / FastCGI
Ограничение памяти: 256 МБ
output_buffering: нет значения

Ниже приведен мой пример кода для отправки события:

<?php
header("Content-Type: text/event-stream");
header("Cache-Control: no-cache");
header("Access-Control-Allow-Origin: *");

$lastEventId = floatval(isset($_SERVER["HTTP_LAST_EVENT_ID"]) ? $_SERVER["HTTP_LAST_EVENT_ID"] : 0);
if ($lastEventId == 0) {
$lastEventId = floatval(isset($_GET["lastEventId"]) ? $_GET["lastEventId"] : 0);
}

echo ":" . str_repeat(" ", 2048) . "\n"; // 2 kB padding for IE
echo "retry: 2000\n";

// event-stream
$i = $lastEventId;

while ($i <= 100) {
if($i==100){
echo "data: stop\n";
ob_flush();
flush();
break;
} else {
echo "id: " . $i . "\n";
echo "data: " . $i . ";\n\n";
ob_flush();
flush();
sleep(1);
}
$i++;
}
?>

Ниже моя страница клиента, на которой мне нужен ответ:

<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8" />
<title>EventSource example</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script src="../jquery/eventsource.js"></script>
<script>
var es = new EventSource("events.php");
var listener = function(event) {
console.log(event.data);
var type = event.type;
if (event.data == 'stop') {
es.close();
} else {
var div = document.createElement("div");
div.appendChild(document.createTextNode(type + ": " + (type === "message" ? event.data : es.url)));
document.body.appendChild(div);
}
};
var errlistener = function(event) {
es.close();
}
es.addEventListener("open", listener);
es.addEventListener("message", listener);
es.addEventListener("error", errlistener);
</script>
</head>

<body>
</body>

</html>

7

Решение

Лучший способ вернуть данные в браузере — это использовать веб-сокеты, чтобы клиент открыл сокет для вашего устройства чтения файлов, и вы можете без проблем разделить данные на части в браузере.

Затем, когда он закончится, вы можете закрыть сокет.

хороший учебник для веб-сокетов
http://www.phpbuilder.com/articles/application-architecture/optimization/creating-real-time-applications-with-php-and-websockets.html

с помощью этого метода вы можете затем, если вы хотите реализовать проверку, чтобы сервер не просто отправлял куски, он отправляет куски по запросу с помощью javascript

Так что ваш клиент может сказать, что мне нужен кусок 5, а ваш сервер реализует что-то вроде

$requestedChunk = 5; // this would be set by the javascript sending the request
$chunkSize = 256; // this would be your chunk size;

$readPossition = $requestedChunk * $chunkSize;

Ссылка больше не работает, поэтому вот такая, построенная на Ratchet: https://blog.samuelattard.com/the-tutorial-for-php-websockets-that-i-wish-had-existed/

6

Другие решения

У меня была похожая проблема. Потоки событий работали, как и ожидалось (возвращая фрагменты) на сервере с использованием обработчика Apache 2.0, но не на сервере с использованием FastCGI (возвращая его навалом). Я предположил, что что-то в FastCGI является виновником, и поэтому попытался решить проблему, переключившись на CGI. Теперь поток событий работает как положено.

Независимо от того, используете ли вы CGI или FastCGI, серверный API отображается как CGI / FastCGI, поэтому я предполагаю, что сервер, на котором он работает для вас, работает под управлением CGI, а сервер, на котором он не работает, работает под управлением FastCGI. Попробуйте изменить нерабочий сервер на CGI.

Что касается того, почему это не работает в FastCGI, я не совсем уверен, но если это не является обязательным требованием и CGI невозможен, то вышеупомянутое решение должно работать.

0

Многие вещи могут предотвратить частичный ответ, например, но не ограничиваясь ими;

  • Прокси или любой другой механизм буферизации на веб-сервере
  • Когда «выходная буферизация» включена в php.ini (вы должны явно отключить ее)
  • Когда gzip включен на веб-сервере

Вы должны проверить это сначала.

0
По вопросам рекламы [email protected]