Продолжайте запускать php-скрипт после возврата страницы

Я пытаюсь написать сценарий, который создаст файл на сервере, а затем с помощью header() перенаправит пользователя к этому файлу. Затем примерно через 10 секунд я хочу удалить файл. Я пробовал это:

header('Location: '.$url);
flush();
sleep(10);
unlink($url);

Но браузер просто ждет завершения скрипта, а затем перенаправляется, но к тому времени файл уже удален. Есть ли способ сообщить браузеру «конец файла», а затем продолжить вычисления? Или, может быть, PHP запустит другой скрипт, но не дождется его завершения?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
6
0
2 287
8

Ответы 8

Вы можете попробовать сделать что-то вроде этого:

<iframe src = "<?=$url?>"></iframe>

....
<?
sleep(10);
unlink($url);
?>

Другой вариант - использовать curl - тогда вы загружаете файл в запрос и отображаете его пользователю.

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

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

Это просто идеи, не знаю, что подойдет вам (если есть :))

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

header("Content-Length: 0");

перед вашим флешем ();

http://us2.php.net/ignore_user_abort

Будьте очень осторожны, используя это, вы можете довольно быстро убить сервер, злоупотребляя им.

Возможно, вам будет лучше, если страница PHP будет обслуживать файл. В этом случае нет необходимости создавать временный файл и удалять его, просто отправьте данные, которые вы намеревались записать, во временный файл. Вам нужно будет правильно установить заголовки, чтобы браузер мог определить тип отправляемого файла. то есть Content-Type: text / xml; для xml или image / jpeg для jpg.

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

Да, создание страницы и последующее ее уничтожение - пустая трата ресурсов, просто распечатайте этот файл пользователю, убивает двух зайцев одним выстрелом. Если вы пытаетесь сделать что-то вроде вывода CSV, печать его в браузере по-прежнему остается лучшим способом.

TravisO 11.12.2008 01:57

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

tempFile.php? key = {md5 hash}

tempFile.php затем запрашивает содержимое базы данных, memcache (с дополнительным ключом) или apc.

Вы идете неверным путем. Вы можете создать файл и передать его им, а также удалить его за один шаг.

<?php
$file_contents = 'these are the contents of your file';
$random_filename = md5(time()+rand(0,10000)).'.txt';
$public_directory = '/www';
$the_file = $public_directory.'/'.$random_filename;
file_put_contents($the_file, $file_contents);
echo file_get_contents($the_file);
unlink($the_file);
?>

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

<?php
$file_contents = 'these are the contents of your file';
echo $file_contents;
?>

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

<?php
$file_contents = file_get_contents($filename_or_url);
echo $file_contents;
?>

Что касается автоматического удаления файлов, просто настройте задание cron, которое запускается каждые 10 секунд и удаляет все файлы в вашей временной папке, где filemtime ($ filename) превышает 5 минут секунд.

Если вы хотите реализовать свой оригинальный дизайн, прочтите этот вопрос о запуске команды в PHP, которая называется «выстрелил и забыл» Асинхронная оболочка exec в PHP

Как видно на \Symfony\Component\HttpFoundation\Response::send

/**
 * Sends HTTP headers and content.
 *
 * @return Response
 *
 * @api
 */
public function send()
{
    $this->sendHeaders();
    $this->sendContent();

    if (function_exists('fastcgi_finish_request')) {
        fastcgi_finish_request();
    } elseif ('cli' !== PHP_SAPI) {
        // ob_get_level() never returns 0 on some Windows configurations, so if
        // the level is the same two times in a row, the loop should be stopped.
        $previous = null;
        $obStatus = ob_get_status(1);
        while (($level = ob_get_level()) > 0 && $level !== $previous) {
            $previous = $level;
            if ($obStatus[$level - 1]) {
                if (version_compare(PHP_VERSION, '5.4', '>=')) {
                    if (isset($obStatus[$level - 1]['flags']) && ($obStatus[$level - 1]['flags'] & PHP_OUTPUT_HANDLER_REMOVABLE)) {
                        ob_end_flush();
                    }
                } else {
                    if (isset($obStatus[$level - 1]['del']) && $obStatus[$level - 1]['del']) {
                        ob_end_flush();
                    }
                }
            }
        }
        flush();
    }

    return $this;
}

Другие вопросы по теме