Страницы

Поиск по вопросам

понедельник, 1 октября 2018 г.

Организация докачки в php HTTP_RANGE

Примеров по реализации достаточно много. Интересует более детальная часть, а именно. Как узнать что файл уже скачался? Ситуация: Скрипт генерит файлы на сервере во временную папку, потом используется скрипт отдачи (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 я не вижу.

Комментариев нет:

Отправить комментарий