readfile()和数据库插入问题

I have a really weird problem regarding a small piece of code in a CodeIgniter application. Basically, there's a page with links to various PDF files. When a user clicks on the link, the request is parsed by PHP, an observer is notified, writing the click event in the database (activity log), and then the file is outputted by using readfile().

So far, so good. Tested it, it works like a charm. The PDF is outputted for download, and the event is written in the database as it should.

The problem comes when a user clicks on such link, then cancels the download and clicks on another link no later than 9-10 seconds. When that happens, the event is registered in the database twice.

I did triple check of the observers that record the event, but they appear to be fine. Besides, there's a similar function for a video links, only it redirects to another page instead of outputting the file directly, and it works just fine.

After a few hours of scratching my head, I figured there's an issue with the readfile() function, because, if I put a var_dump();die(); or anything that outputs some text before the download and force it to come as text, the download event is recorded only once.

Here's the code in question:

public function downloadPDF($id = NULL)
{
    if (($id == NULL) OR (!$this->validateId($id))) {
        // redirect with error
    }   

    $item = // code for fetching the PDF properties from the DB

    $this->notify('ActivityObserver'); // writes the download event in the DB

    $file = '.' . urldecode($item['link']);
    $size = filesize($file);
    $name = urldecode(basename($file));

    header('Content-Description: File Transfer');
    header('Content-Type: application/pdf');
    header("Content-Disposition: attachment; filename=\"$name\"");
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));

    readfile($file);
    exit();
}

Tried to test it with different browsers, the behaviour is the same. All inspector tools show only 1 request being made on click.

What am I missing in this big ugly picture? Why could it sometimes write twice instead of only once?

Thanks for your time to read this wall of text.