# Отслеживание хода загрузки файлов через сессии

PHP умеет отслеживать ход загрузки отдельных файлов, если включить INI-директиву session.upload_progress.enabled. Эта информация не приносит пользы самому запросу на отправку файла, но во время загрузки файла приложение может отправить POST-запрос отдельной конечной точке, например через интерфейс XHR, чтобы проверить статус.

Ход загрузки будет доступен в суперглобальной переменной $_SESSION по мере загрузки файла, и при отправке POST-переменной с тем же именем, которое установили для INI-параметра session.upload_progress.name. Когда PHP обнаруживает такие POST-запросы, он заполняет в переменной $_SESSION массив, в котором ключом будет конкатенация значений опций session.upload_progress.prefix и session.upload_progress.name. Ключ обычно получают путём чтения значений этих директив, то есть:

    <?php

    $key = ini_get("session.upload_progress.prefix") . $_POST[ini_get("session.upload_progress.name")];
    var_dump($_SESSION[$key]);

    ?>

Разработчики отменяют текущую загрузку файла через установку для ключа `$_SESSION[$key]["cancel_upload"]` значения `true`, когда требуется. При загрузке набора файлов в одном запросе этот способ отменит только текущую загрузку файла, которая уже началась, и загрузки в очереди, но не удалит загрузки, которые уже завершились. При отмене загрузки таким способом PHP установит элементу массива $_FILES с ключом `error` значение константы `UPLOAD_ERR_EXTENSION`.

Директивы session.upload_progress.freq и session.upload_progress.min_freq определяют, как часто требуется обновлять информацию о ходе загрузки. Накладные расходы на эту функцию не ощущаются при разумных значениях этих настроек.

Пример #1 Пример информации

Пример структуры массива прогресса загрузки.

    <form action="upload.php" method="POST" enctype="multipart/form-data">
        <input type="hidden" name="<?php echo ini_get("session.upload_progress.name"); ?>" value="123" />
        <input type="file" name="file1" />
        <input type="file" name="file2" />
        <input type="submit" />
    </form>

Данные, которых хранятся в сессии, будут выглядеть вот так:

    <?php
    $_SESSION["upload_progress_123"] = array(
        "start_time" => 1234567890,   // Время начала запроса
        "content_length" => 57343257, // Длина содержимого POST-запроса
        "bytes_processed" => 453489,  // Количество байтов, которые получил и обработал запрос
        "done" => false,              // После завершения обработки POST-запроса значение изменится на true,
                                      // независимо от того, успешно или нет завершилась обработка
        "files" => array(
            0 => array(
                "field_name" => "file1",       // Значение атрибута name поля <input/>
                // Следующие 3 элемента соответствуют элементам суперглобального массива $_FILES
                "name" => "foo.avi",
                "tmp_name" => "/tmp/phpxxxxxx",
                "error" => 0,
                "done" => true,                // Элемент получает значение true, когда обработчик POST-запроса
                                               // закончил обработку файла
                "start_time" => 1234567890,    // Время начала обработки файла
                "bytes_processed" => 57343250, // Количество байтов, которые запрос получил и обработал для файла
            ),
            // Ещё один файл, загрузка которого ещё не закончилась в том же запросе
            1 => array(
                "field_name" => "file2",
                "name" => "bar.avi",
                "tmp_name" => NULL,
                "error" => 0,
                "done" => false,
                "start_time" => 1234567899,
                "bytes_processed" => 54554,
            ),
        )
    );

    ?>

Внимание

Для правильной работы требуется отключить буферизацию запросов веб-сервера, иначе PHP увидит загрузку файла только после полной загрузки. Серверы наподобие Nginx буферизуют большие запросы.

Предостережение

Информация о ходе загрузки записывается в сессию перед выполнением скриптов. Поэтому PHP начнёт сессию без информации о ходе загрузки, если изменить название сессии функцией ini_set() или session_name().

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open