Home » Php » PHP – simple download script

PHP – simple download script

Posted by: admin July 12, 2020 Leave a comment

Questions:

I’m making a simple download script, where my users can download their own images etc.

But I’m having some weird problem.

When I’ve downloaded the file, it’s having the contents from my index.php file no matter what filetype I’ve downloaded.. My code is like so:

$fullPath = $r['snptFilepath'] . $r['snptFilename'];

if (file_exists($fullPath)) {

    #echo $fullPath;

    // setting headers
    header('Content-Description: File Transfer');
    header('Cache-Control: public'); # needed for IE
    header('Content-Type: '.$r['snptFiletype'].'');
    header('Content-Disposition: attachment; filename='. $filename . '.' . $r['snptExtension']);
    header('Content-Length: '.$r['snptSize'].'');
    readfile($fullPath)or die('error!');
} else {
    die('File does not exist');
}

$r is the result from my database, where I’ve stored size, type, path etc. when the file is uploaded.

UPDATE

When I’m uploading and downloading *.pdf files it’s working with success. But when I’m trying to download *.zip and text/rtf, text/plain it’s acting weird.

By weird I mean: It downloads the full index.php file, with the downloaded file contents inside of it.

ANSWER

I copied this from http://php.net/manual/en/function.readfile.php and it’s working now. It seems that : ob_clean(); did the trick! Thanks for the help everyone.

#setting headers
    header('Content-Description: File Transfer');
    header('Content-Type: '.$type);
    header('Content-Disposition: attachment; filename='.basename($file));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    ob_clean();
    flush();
    readfile($file);
    exit;
How to&Answers:

Try this function , or implement these headers to your code

    function force_download($filename) {
    $filedata = @file_get_contents($filename);

    // SUCCESS
    if ($filedata)
    {
        // GET A NAME FOR THE FILE
        $basename = basename($filename);

        // THESE HEADERS ARE USED ON ALL BROWSERS
        header("Content-Type: application-x/force-download");
        header("Content-Disposition: attachment; filename=$basename");
        header("Content-length: " . (string)(strlen($filedata)));
        header("Expires: ".gmdate("D, d M Y H:i:s", mktime(date("H")+2, date("i"), date("s"), date("m"), date("d"), date("Y")))." GMT");
        header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");

        // THIS HEADER MUST BE OMITTED FOR IE 6+
        if (FALSE === strpos($_SERVER["HTTP_USER_AGENT"], 'MSIE '))
        {
            header("Cache-Control: no-cache, must-revalidate");
        }

        // THIS IS THE LAST HEADER
        header("Pragma: no-cache");

        // FLUSH THE HEADERS TO THE BROWSER
        flush();

        // CAPTURE THE FILE IN THE OUTPUT BUFFERS - WILL BE FLUSHED AT SCRIPT END
        ob_start();
        echo $filedata;
    }

    // FAILURE
    else
    {
        die("ERROR: UNABLE TO OPEN $filename");
    }
}

Answer:

I copied this from http://php.net/manual/en/function.readfile.php and it works now. ob_clean(); did the trick..

    #setting headers
    header('Content-Description: File Transfer');
    header('Cache-Control: public');
    header('Content-Type: '.$type);
    header("Content-Transfer-Encoding: binary");
    header('Content-Disposition: attachment; filename='. basename($file));
    header('Content-Length: '.filesize($file));
    ob_clean(); #THIS!
    flush();
    readfile($file);