public static function download($location, $filename = null, $mime = 'application/octet-stream', $speed = 1024, $disposition = 'attachment')
    {
        if (connection_status() != 0) return(false);

        if(!is_file($location))
        {
            http_response_code(404);
            exit();
        }

        if (empty($mime))
        {
            $mime = static::getFileMime($location);
        }

        set_time_limit(0);

        while (ob_get_level() > 0)
        {
            ob_end_clean();
        }

        if (!$filename)
        {
            $filename = pathinfo($location, PATHINFO_BASENAME);
        }

        $time = date('r', filemtime($location));
        $size = filesize($location);
        $speed = ($speed === null) ? 1024 : intval($speed) * 1024;
        $begin = 0;
        $end = $size;
        $status = 200;

        if(isset($_SERVER['HTTP_RANGE']))
        {
            if(preg_match('/bytes=\h*(\d+)-(\d*)[\D.*]?/i', $_SERVER['HTTP_RANGE'], $matches))
            {
                $begin = intval($matches[0]);

                if(!empty($matches[1]))
                {
                    $end = intval($matches[1]);
                }

                $status = 206;
            }
        }

        http_response_code($status);

        header('Expires: 0');
        header("Content-Type: $mime");
        header('Pragma: public');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Accept-Ranges: bytes');
        header('Content-Length: '.($end - $begin));
        header("Content-Range: bytes $begin-" . ($end - 1) . "/$size");
        header("Content-Disposition: " . $disposition . "; filename=$filename");
        header("Content-Transfer-Encoding: binary");
        header("Last-Modified: $time");
        header('Connection: close');

        for ($offset = $begin; $offset <= $end; $offset += $speed)
        {
            if (connection_status() || connection_aborted())
            {
                exit(1);
            }

            echo file_get_contents($location, false, null, $offset, $speed);

            while (ob_get_level() > 0)
            {
                ob_end_flush();
            }

            flush();
            //ob_flush();
            //ob_implicit_flush();

            usleep(intval(floatval($time) * 1000000));
        }

        return ((connection_status()==0) and !connection_aborted());
    }