Примеров по реализации достаточно много. Интересует более детальная часть, а именно. Как узнать что файл уже скачался? Ситуация: Скрипт генерит файлы на сервере во временную папку, потом используется скрипт отдачи (http_range, 206 partial content и т.д.). Как мне узнать когда можно его удалять. Предложения с кроном не предлагать!
Ответ
Определить в PHP, что файл был гарантированно скачен, к сожалению, не удастся. Однако, если в качестве фронтенда используется nginx, то можно, по крайне мере, гарантировано убедится, что файл (в данном случае часть файла) был отдан.
В nginx имеется директива post_action, которая делает повторный внутренний запрос уже после того, как ответ уже был отправлен клиенту. Соответственно, благодаря ней можно узнать сколько реально данных было отправлено клиенту. Выглядеть конфиг будет примерно так:
# скрипт, который отдает файл по частям
location = /download.php {
fastcgi_pass localhost:9000;
fastcgi_param SCRIPT_FILENAME /var/www/localhost/htdocs/$fastcgi_script_name;
include fastcgi_params;
post_action /complete;
}
# а этот скрипт уже будет подсчитывать байты
location = /complete {
internal;
fastcgi_pass localhost:9000;
fastcgi_param SCRIPT_FILENAME /var/www/localhost/htdocs/complete.php;
# количество отправленных клиенту байт
fastcgi_param BYTE-SEND $body_bytes_sent;
# заголовок Range
fastcgi_param RANGE $http_range;
include fastcgi_params;
}
После того, как download.php отправит очередной кусок файла, nginx сделает внутренний запрос к complete.php, где в $_SERVER['BYTE-SEND'] будет количество отправленных байт, а в $_SERVER['BYTE-SEND'] заголовок Range от клиента.
Ну а дальше уже дело техники. Считаем где-нибудь (например в сессии) байты или для большей надежности лучше промежутки Range. И кода количество отданных байт будет равно размеру файла - значит файл был отдан целиком.
PS К сожалению директива post_action не задокументирована.
UPD. Если PHP работает через fastcgi или за ним стоит любой reverse-proxy (опять же nginx например), то на самом PHP определять это бесполезно. После того как PHP отдаст веб-серверу кусок данных, дальнейшая судьба о нем ему уже не известна.
Если же PHP работает на apache через mod_php без каких-либо reverse-proxy, тогда, вероятно, еще с натяжкой можно считать, что после flush() данные ушли клиенту.
Еще один способ, это отдавать файл напрямую через socket'ы. Т.е. написать скрипт, который бы сам выступал в качестве веб-сервера. Однако это крайне не производительное решение.
Все, других вариантов на PHP я не вижу.
Комментариев нет:
Отправить комментарий