Подтвердить что ты не робот

Как очистить данные от браузера, но продолжить выполнение

У меня есть ob_start() и соответствующий ob_flush(). Я хотел бы очистить часть данных и продолжить выполнение остальных. Использование ob_flush() не помогло. Также, если это возможно, отдых должен происходить без отображения загрузки в браузере.

EDIT:

Я не хочу использовать ajax

4b9b3361

Ответ 1

ob_flush записывает буфер. Другими словами, ob_flush сообщает PHP, чтобы предоставить выход Apache (или nginx/lighttpd/whatever), а затем PHP забыть об этом. Как только Apache имеет выход, он делает все, что захочет. (Другими словами, после ob_flush он не контролируется независимо от того, сразу ли он попадает в браузер).

Итак, короткий ответ: нет гарантированного способа сделать это.

Просто предположим, вы, скорее всего, ищете AJAX. Всякий раз, когда люди пытаются манипулировать при загрузке содержимого страницы, как вы делаете, AJAX почти всегда является правильным путем.

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

Я бы попытался извлечь его из Интернета. Это может означать запись cron или просто появление фонового процесса изнутри PHP (процесс, который, хотя и запущен изнутри script, не будет умирать с помощью script, а script не будет ждать завершения перед смертью).

Если вы поедете по этому маршруту, это будет означать, что вы можете даже сделать какую-то систему статуса, если это необходимо. Затем вы можете следить за выполнением и периодически предоставлять пользователям обновления. (Технически вы можете создать систему состояния с помощью ignore_user_abort -ed script, но для меня это не выглядит так чисто.)

Ответ 2

Я сделал это в прошлом, и именно так я решил это:

ob_start();

/*
 * Generate your output here
 */ 

// Ignore connection-closing by the client/user
ignore_user_abort(true);

// Set your timelimit to a length long enough for your script to run, 
// but not so long it will bog down your server in case multiple versions run 
// or this script get in an endless loop.
if ( 
     !ini_get('safe_mode') 
     && strpos(ini_get('disable_functions'), 'set_time_limit') === FALSE 
){
    set_time_limit(60);
}

// Get your output and send it to the client
$content = ob_get_contents();         // Get the content of the output buffer
ob_end_clean();                      // Close current output buffer
$len = strlen($content);             // Get the length
header('Connection: close');         // Tell the client to close connection
header("Content-Length: $len");     // Close connection after $len characters
echo $content;                       // Output content
flush();                             // Force php-output-cache to flush to browser.
                                     // See caveats below.

// Optional: kill all other output buffering
while (ob_get_level() > 0) {
    ob_end_clean();
}

Как я уже говорил в нескольких комментариях, вы должны следить за gzipping своим контентом, поскольку это изменит длину вашего контента, но не изменит заголовок об этом. Он также может буферизовать ваш вывод, поэтому он не будет сразу отправлять клиенту.
Вы можете попытаться позволить apache знать, чтобы не gzip ваш контент, используя apache_setenv('no-gzip', '1');. Но это не сработает, если вы используете правила перезаписи, чтобы перейти на вашу страницу, так как тогда он также изменит эти переменные среды. По крайней мере, он сделал это для меня.

См. дополнительные предупреждения о том, как очистить содержимое от пользователя в manual.

Ответ 3

это моя функция

function bg_process($fn, $arr) {
    $call = function($fn, $arr){
        header('Connection: close');
        header('Content-length: '.ob_get_length());
        ob_flush();
        flush();
        call_user_func_array($fn, $arr);
        };
    register_shutdown_function($call, $fn, $arr);
    }

завершите функцию, которая будет выполнена в конце, после закрытия php соединения. и, конечно, браузер остановит буферизацию.

function test() {
    while (true) {
        echo 'this text will never seen by user';
        }
    }

вот как вызвать функцию

bg_process('test'); 

первый аргумент callable, второй аргумент - это массив, который должен быть передан функции "test" с индексированным массивом

Примечание. Я не использую ob_start() в начале script.

Ответ 5

Использование:

header("Content-Length: $len");

.. где $len - длина данных, которые должны быть сброшены клиенту.

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

<?PHP 
    header("Content-length:5");
    echo "this is more than 5";
    sleep(5);
?>

edit: Chrome, IE и Opera показали this, в то время как FireFox показал this is more than 5. Однако все они закрыли запрос.