Потоковый вывод в файл и браузер - PullRequest
12 голосов
/ 06 марта 2009

Итак, я ищу что-то более эффективное, чем это:

<?php
ob_start();
include 'test.php';
$content = ob_get_contents();

file_put_contents('test.html', $content);

echo $content;
?>

Проблемы с вышесказанным:

  • Клиент ничего не получает, пока вся страница не будет отображена
  • Файл может быть огромным, поэтому я бы предпочел не хранить все это в памяти

Есть предложения?

Ответы [ 4 ]

6 голосов
/ 06 марта 2009

Интересная проблема; не думаю, что я пытался решить это раньше.

Я думаю, вам понадобится второй запрос, идущий от вашего переднего PHP-скрипта к вашему серверу. Это может быть простой вызов http://localhost/test.php. Если вы используете fopen-wrappers, вы можете использовать fread (), чтобы получить выходные данные test.php по мере их визуализации, и после получения каждого чанка вывести его на и добавьте его в файл test.html.

Вот как это может выглядеть (не проверено!):

<?php
$remote_fp = fopen("http://localhost/test.php", "r");
$local_fp = fopen("test.html", "w");
while ($buf = fread($remote_fp, 1024)) {
    echo $buf;
    fwrite($local_fp, $buf);
}
fclose($remote_fp);
fclose($local_fp);
?>
2 голосов
/ 07 мая 2016

Лучший способ сделать это - использовать первые два параметра, принятые ob_start: output_callback и chunk_size. В первом указывается обратный вызов для обработки вывода по мере его буферизации, а во втором - размер фрагментов вывода для обработки.

Вот пример:

$output_file = fopen('test.html', 'w');
if ($output_file === false) {
    // Handle error
}

$write_ob_to_file = function($buffer) use ($output_file) {
    fwrite($output_file, $buffer);

    // Output string as-is
    return false;
};

ob_start($write_ob_to_file, 4096);
include 'test.php';
ob_end_flush();

fclose($output_file);

В этом примере выходной буфер будет очищаться (отправляться) на каждые 4096 байтов вывода (и еще раз в конце при вызове ob_end_flush). Каждый раз, когда буфер очищается, будет вызван обратный вызов $write_ob_to_file и передан последний фрагмент. Это записывается в test.html. Затем обратный вызов возвращает false, что означает «выводить этот блок как есть». Если вы хотите записать только выходные данные в файл, а не в выходной поток PHP, вы можете вместо этого вернуть пустую строку.

0 голосов
/ 06 марта 2009

Вот, пожалуйста, x-send-file , используйте mod_xsendfile для эффективной, очень простой отправки файла.

0 голосов
/ 06 марта 2009

Ответ Pix0r - это то, что вы хотите, если только вам на самом деле не нужно, чтобы оно «включалось», а не просто выполнялось. Например, если у вас есть информация для входа до test.php, она не будет передана в файл, если вы вызовете ее с помощью fopen.

Если вам нужно, чтобы он был действительно включен, то у вас есть самый простой способ, но если вам нужен постоянный вывод, вам нужно будет на самом деле написать test.php таким способом, который выводит, а также сохраняет информацию по мере ее поступления. , Насколько я знаю, нет способа собрать буфер и вывести его на ходу.

...