Search code examples
phpdownload

The file download is interrupted many times


I have a PHP site on which the user can download file. Here is the code:

if (isset($_SERVER['HTTP_RANGE']))
{
    $partialContent = true;
    preg_match('/bytes=(\d+)-(\d+)?/', $_SERVER['HTTP_RANGE'], $matches);
    $offset = intval($matches[1]);
    $length = (isset($matches[2]) ? intval($matches[2]) : $filesize) - $offset;
}
else
    $partialContent = false;
if (ob_get_level())
    ob_end_clean();
header('Pragma: public');
header('Expires: -1');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Content-Type: application/octet-stream');
if ($partialContent)
{
    header('HTTP/1.1 206 Partial Content');
    header('Content-Range: bytes '.$offset.'-'.($offset + $length - 1).'/'.$filesize);
}
header('Content-Length: '.$length);
header('Accept-Ranges: bytes');
if ($fd = fopen($file, 'rb'))
{
    fseek($fd, $offset);
    $chunk = 1024 * 1024;
    while (!feof($fd))
    {
        print fread($fd, $chunk);
        $length -= $chunk;
        if (ob_get_level() > 0)
            ob_flush();
        flush();
        if (connection_status() != 0)
        {
            @fclose($fd);
            return;
        }
    }
    fclose($fd);
}

The file is being downloaded but the problem is that the downloading is being interrupted many times (for example, on my computer on the 2 GB file - ~30-50 times but it is a floating value), and every time one needs to press "Resume" in the browser menu. Where can be the ground of this problem?


Solution

  • Thanks to @KIKOSoftware, the problem has now been fixed. One needs using set_time_limit(). Here is the working version of the code:

    if (isset($_SERVER['HTTP_RANGE']))
    {
        $partialContent = true;
        preg_match('/bytes=(\d+)-(\d+)?/', $_SERVER['HTTP_RANGE'], $matches);
        $offset = intval($matches[1]);
        $length = (isset($matches[2]) ? intval($matches[2]) : $filesize) - $offset;
    }
    else
        $partialContent = false;
    if (ob_get_level())
        ob_end_clean();
    header('Pragma: public');
    header('Expires: -1');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Content-Disposition: attachment; filename="'.basename($file).'"');
    header('Content-Type: application/octet-stream');
    if ($partialContent)
    {
        header('HTTP/1.1 206 Partial Content');
        header('Content-Range: bytes '.$offset.'-'.($offset + $length - 1).'/'.$filesize);
    }
    header('Content-Length: '.$length);
    header('Accept-Ranges: bytes');
    if ($fd = fopen($file, 'rb'))
    {
        fseek($fd, $offset);
        $chunk = 1024 * 1024;
        while (!feof($fd))
        {
            set_time_limit(60);
            print fread($fd, $chunk);
            $length -= $chunk;
            if (ob_get_level() > 0)
                ob_flush();
            flush();
            if (connection_status() != 0)
            {
                @fclose($fd);
                return;
            }
        }
        fclose($fd);
    }