How to check if PHP download was canceled?

I need to log total downloads of an specific file. Download function is working fine, but can't define if user canceled (clicking "cancel" on browser dialog) or if connection was aborted latter.
I understand it's not simple to know when a file download was finished, so I'm trying to get this by two ways. None works:

  1. Get total bytes sent, latter I will compare it with total file size: this way $bytes_sent var always is set with total file size, no matter if user click cancel button of download dialog or if cancel download process latter.
  2. Trigger connection_aborted() function: Have not found the way this function happen and define my session var...

(I'm not shure if the fact Im working with sessions is relevant).

I appreciate your help :)

<?php
if(is_file($filepath)){
    $handle = fopen($filepath, "r");

    header("Content-Type: $mime_type");
    header("Content-Length: ". filesize($filepath).";");
    header("Content-disposition: attachment; filename=" . $name);

    while(!feof($handle)){
        ignore_user_abort(true);
        set_time_limit(0);
        $data = fread($handle, filesize($filepath));
        print $data;
        $_SESSION['download'] = 'Successful download';
        //Always is set as total file lenght, even when cancel a large file download before it finish:
        bytes_sent = ftell($handle);
        flush();
        ob_flush();
        //Can't trigger connection aborted, in any case:
        if(connection_aborted()){
            $_SESSION['download'] = 'Canceled download';
        }
    }
} 

PHP Version 5.3.29

Upvotes: 1

Views: 481

Answers (1)

Barmar
Barmar

Reputation: 781098

You need to read the file in small chunks, rather than reading it all in at once.

$chunk_size = 1000;
ignore_user_abort();
$canceled = false;
while ($chunk = fread($handle, $chunk_size)) {
    print $chunk;
    ob_flush();
    $bytes_sent += strlen($chunk);
    if (connection_aborted()) {
        $canceled = true;
        break;
    }
}
$_SESSION['download'] = $canceled ? "Download canceled" : "Download successful";

Upvotes: 1

Related Questions