Organization of resume in php HTTP_RANGE

Question:

There are a lot of examples of implementation. The more detailed part interests, namely. How do I know if a file has already been downloaded?

Situation: The script generates files on the server in a temporary folder, then the upload script is used (http_range, 206 partial content, etc.). How do I know when I can delete it.

Do not offer offers with a crown!

Answer:

Unfortunately, it will not be possible to determine in PHP that the file was guaranteed to be downloaded. However, if nginx is used as a frontend, then you can at least make sure that the file (in this case, part of the file) was served.

Nginx has a post_action directive that makes a repeated internal request after the response has already been sent to the client. Accordingly, thanks to it, you can find out how much data was actually sent to the client. The config will look something like this:

# скрипт, который отдает файл по частям
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;
}

After download.php sends another piece of file, nginx will make an internal request to complete.php, where $_SERVER['BYTE-SEND'] will $_SERVER['BYTE-SEND'] number of bytes sent, and $_SERVER['BYTE-SEND'] Range header from the client.

Well, then it's already a matter of technology. We count somewhere (for example, in a session) bytes or, for greater reliability, Range gaps are better. And if the number of bytes sent will be equal to the file size, then the file was sent in its entirety.

PS Unfortunately the post_action directive is not documented.

UPD. If PHP works through fastcgi or there is any reverse-proxy behind it (again, for example, nginx), then it is useless to define this in PHP itself. After PHP gives the web server a piece of data, its further fate is no longer known to it.

If PHP runs on apache via mod_php without any reverse-proxy, then it is probably still a stretch to assume that after flush() data went to the client.

Another way is to send the file directly via sockets. Those. write a script that itself would act as a web server. However, this is an extremely inefficient solution.

That's it, I don't see any other options in PHP.

Scroll to Top