Я потратил уже более двух дней на эту проблему. Похоже, что функция PHP connection_aborted () не работает надежно. Иногда он сообщает о прерывании связи с клиентом должным образом, но примерно в 50% он не сообщает об отмене.
Есть ли другой способ обнаружить прерывание соединения с клиентом из PHP-скрипта, пожалуйста? Может быть, установить соединение сокета или что-нибудь еще?
Это моя последняя версия кода загрузки файла. Загрузка выполняется корректно даже в больших файлах, но connection_aborted()
работает только изредка.
// disable script abort ignore_user_abort(true); // never expire this download script set_time_limit(0); while(!feof($fileObject) && (connection_status()==0)) { //usleep(100000); print(@fread($fileObject, $chunkSize)); // gradually output buffer to avoid memory problems by downloading large files ob_flush(); flush(); $nLoopCounter++; $transferred += $chunkSize; $downloadPercentage = (($nLoopCounter * $chunkSize) / $fileSize) * 100; $result = mysqli_query($dbc, "UPDATE current_downloads SET progress_percent=$downloadPercentage, transferred=$transferred, connection_aborted=$strConnectionAborted, iteration=$nLoopCounter WHERE user_id=1;"); if($result == false) { // close the database connection mysqli_close($dbc); // close the file fclose($handle); // prepare output message exit(json_encode(array("result" => false, "error" => "Error Processing Database Query."))); } } // check if the client was disconnected // important for cancelled or interrupted downloads if ( (connection_status()!=0) || (connection_aborted()!=0) ) { // empty the output buffer ob_flush(); flush(); ChromePhp::log("Connection Aborted"); // sent to the database that the connection has been aborted $result = mysqli_query($dbc, "UPDATE current_downloads SET connection_aborted=TRUE WHERE user_id=1;"); // close the database connection mysqli_close($dbc); // close the open file @fclose($fileObject); exit(json_encode(array("result" => false, "error" => "Connection with the client was aborted."))); }
Спасибо и любезны.
С настройками по умолчанию PHP просто прекратит выполнение сценария, если браузер закрывает соединение. Вы можете изменить это поведение по умолчанию, используя функцию ignore_user_abort()
или параметр ini ignore_user_abort
.
Чтобы использовать функцию connection_aborted()
вам нужно выполнить один из этих шагов, потому что иначе connection_aborted()
никогда не достигнет. Вот пример с ignore_user_abort()
:
ignore_user_abort(TRUE); for($i = 0; $i < 10; $i++) { sleep(1); // click the stop button in your browser ... if(connection_aborted()) { // we can't use echo anymore as the connection to the // browser was closed. that's why we write to test file file_put_contents('/tmp/test.file', 'The connection was aborted'); } }
Но это не все. Если вы зарегистрируете функцию выключения с помощью register_shutdown_function()
эта функция будет вызвана, даже если скриптам было сказано завершить работу из-за отсутствия ignore_user_abort()
. Следующий пример показывает это:
register_shutdown_function(function() { // click the stop button in your browser ... if(connection_aborted()) { // we can't use echo anymore as the connection to the // browser was closed. that's why we write to test file file_put_contents('/tmp/test.file', 'The connection was aborted'); } });
Вы можете ознакомиться с этой статьей в документации: http://www.php.net/manual/en/features.connection-handling.php . Это объясняет обработку соединений PHP.