Intereting Posts
Laravel catch TokenMismatchException почта php не может быть отправлена ​​с smtp.gmail.com Клиент в DART-сообществе с сервером на PHP: управление доступом позволяет пропустить заголовки источника Как разбирать пространства имен xml с DOMDocument и обязательно получать объекты Openshift: управление процессами cron функция доступности домена php где является фатальной ошибкой «Не удается получить доступ к пустому свойству» в функции класса PHP? используя glob, чтобы возвращать список папок в заданном каталоге (без путей) Datatables – выход Json – PostgreSQL – возвращает значение null Получить идентификатор соединения PDO Хранение значений $ _POST в массиве для сохранения их в текстовый файл Комбинированные объекты на основе выбранного элемента в другом поле со списком Почтовые данные PHP через VPN Как отключить скомпилированное расширение в PHP Преобразование таблицы MySQL по отношению к многомерному массиву

Продолжить php-скрипт после закрытия соединения

Я пытаюсь продолжить PHP-скрипт после закрытия страницы / подключения.

Пользователи будут ЗАГРУЗИТЬ скрипт каждые 1 час, я хочу вернуть некоторый вывод json и хочу продолжить сценарий в фоновом режиме. Я использую общий хост, и я не могу использовать работу cron.

Вот что я пробовал.

ob_start(); ignore_user_abort(); echo "JSON_OUTPUT GOES HERE"; $ob_length = ob_get_length(); header("Content-Type : text/plain",TRUE); header("Content-Length : $ob_length",TRUE); header("Connection : Close",TRUE); flush(); ob_flush(); ob_end_flush(); sleep(3); echo "You cant see me.."; exit(); 

Я использую Codeigniter framework, но его не работает на моем реальном сервере. Он ждет 3 секунды, а затем выводя You cant see me.. тоже.

Пожалуйста, помогите мне.

Заметка

Проект размещается в общих хостах LINUX / WINDOWS / WAMP-SERVER.

После некоторых исследований я получил его работу, Иногда это может быть полезно для некоторых других.

 function closeOutput($stringToOutput){ set_time_limit(0); ignore_user_abort(true); header("Connection: close\r\n"); header("Content-Encoding: none\r\n"); ob_start(); echo $stringToOutput; $size = ob_get_length(); header("Content-Length: $size",TRUE); ob_end_flush(); ob_flush(); flush(); } 

Вы можете использовать его как

 $outputContent = 'Contentent Goes Here...'; closeOutput( $outputContent ); sleep(5); //do some background works ... exit(); 

Во-первых, не используйте пробел после Connection и до : он должен быть Header: value не Header : value . Во-вторых, Connection: close не заставляют браузер перестать получать текущий ответ и отображать пустую страницу. Здесь http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html глава 14.10 в нем говорится: Connection: close in either the request or the response header fields indicates that the connection SHOULD NOT be considered 'persistent' (section 8.1) after the current request/response is complete

Итак, как вы можете попробовать, если ваш код работает:

 ignore_user_abort(); header("Content-Type: text/plain; charset=UTF-8"); // just to try show following echo immediately, working depends on server configuration while (@ob_end_flush()); echo date('Ymd H:i:s'), PHP_EOL; echo "JSON_OUTPUT GOES HERE", PHP_EOL; sleep(10); // 10 seconds so you can close browser tab before // this file should be created after 10 seconds, even after you closed browser tab // also check if permissions to write to __DIR__ are set for apache. file_put_contents(__DIR__ . '/tmp.txt', "Text after 10 sec"); exit; 

Откройте этот php-файл в браузере и через 2-3 секунды закройте вкладку (даже если вы ничего не видите на экране), подождите немного дольше и проверьте, создан ли файл. Он работает на моей Linux-машине.

Из-за этой прекрасной возможности, которую опубликовал Red, я написал небольшой класс утилиты, который предоставляет очередь, в которую вы можете добавить Closures для последующего исполнения:

 <?php namespace Company\Project\Utilities; /** * Class ContinueUtility * * @package Company\Project\Utilities */ class ContinueUtility { /** * Stored tasks * @var array */ static protected $tasks = array(); /** Constant for new line in HTTP Header */ const HEADER_NEW_LINE = "\r\n"; /** * Add task (closure/function) to queue, with set arguments * * @param \Closure $task * @param array $arguments * @return void */ public static function addTask(\Closure $task, array $arguments = array()) { self::$tasks[] = array( 'closure' => $task, 'arguments' => $arguments ); } /** * Returns TRUE if tasks has been set, otherwise FALSE * * @return boolean */ public static function hasTasks() { return !empty(self::$tasks); } /** * Clear all previous set tasks * * @return void */ protected static function clearTasks() { self::$tasks = array(); } /** * Execute all previous set tasks * * @return void */ protected static function executeTasks() { foreach (self::$tasks as $task) { call_user_func_array($task['closure'], $task['arguments']); } } /** * Execute and clear all previous set tasks * * @return void */ public static function executeAndClearTasks() { self::executeTasks(); self::clearTasks(); } /** * Closes the HTTP connection to client immediately and outputs given string. * * @param string $instantOutput * @return void */ public static function closeConnection($instantOutput = '') { set_time_limit(0); ignore_user_abort(TRUE); header('Connection: close' . self::HEADER_NEW_LINE); header('Content-Encoding: none' . self::HEADER_NEW_LINE); ob_start(); echo $instantOutput; $size = ob_get_length(); header('Content-Length: ' . $size, TRUE); ob_end_flush(); ob_flush(); flush(); } } 

Вот как вы добавляете новые задачи в очередь:

 use Company\Project\Utilities\ContinueUtility; $a = 4; $b = 5; ContinueUtility::addTask(function($a, $b){ sleep(5); $c = a + b; file_put_contents(__DIR__ . '/whatever.log', $a . '+' . $b . '=' . $c); }, array( $a, $b )); 

И вот как вы запускаете выполнение всех предыдущих добавленных задач:

 ContinueUtility::closeConnection('Ready.'); ContinueUtility::executeAndClearTasks();