Отслеживание хода загрузки файлов через сессии
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.
Ключ обычно получают путём чтения значений этих директив, то есть:
]]>
Разработчики отменяют текущую загрузку файла через установку
для ключа $_SESSION[$key]["cancel_upload"] значения &true;, когда требуется.
При загрузке набора файлов в одном запросе этот способ отменит
только текущую загрузку файла, которая уже началась, и загрузки в очереди,
но не удалит загрузки, которые уже завершились.
При отмене загрузки таким способом PHP установит элементу массива
$_FILES с ключом error
значение константы UPLOAD_ERR_EXTENSION.
Директивы session.upload_progress.freq
и session.upload_progress.min_freq
определяют, как часто требуется обновлять информацию о ходе загрузки.
Накладные расходы на эту функцию не ощущаются при разумных значениях этих настроек.
Пример информации
Пример структуры массива прогресса загрузки.
" value="123" />
]]>
Данные, которых хранятся в сессии, будут выглядеть вот так:
1234567890, // Время начала запроса
"content_length" => 57343257, // Длина содержимого POST-запроса
"bytes_processed" => 453489, // Количество байтов, которые получил и обработал запрос
"done" => false, // После завершения обработки POST-запроса значение изменится на true,
// независимо от того, успешно или нет завершилась обработка
"files" => array(
0 => array(
"field_name" => "file1", // Значение атрибута name поля
// Следующие 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.