PHP - Force file to download - not working

keith1001
keith1001 used Ask the Experts™
on
I'm trying to force the download of a file instead of displaying it in a browser and the below code allows me to download the file, but seems not to get the full file.  I can not display any of the jpgs that I download.  Any ideas on what I have wrong?  Keep in mind images may be just one type of a download, as there could be .txt or .pdf etc...

<?php
$file="c:\upload_test\\robot-100_1.jpg"; //file location 
header("Content-Description: File Transfer"); 
header("Content-Type: application/octet-stream");
header('Content-Disposition: attachment; filename="'.basename($file).'"'); 
header('Content-Length: ' . filesize($file));
header('Connection: close');
readfile($file);

?>

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Mukesh YadavFull Stack Developer

Commented:
Remove line 7.

File is not downloading because you are saying browser that connection is closed. After receiving this header browser closes connection.

Author

Commented:
Even if I remove line 7, same issue.

Also changed line 4 to :  image/jpg

It always appears the file is just a little smaller than what is suppose to be.
Mukesh YadavFull Stack Developer

Commented:
Means you are getting file smaller than it is actually?
Fundamentals of JavaScript

Learn the fundamentals of the popular programming language JavaScript so that you can explore the realm of web development.

Fixer of Problems
Most Valuable Expert 2014
Commented:
This is Ray Paseur's download demo that works 'perfectly'.  I modified one line to use a local file on my system.
<?php // RAY_force_download.php
error_reporting(E_ALL);

// DEMONSTRATE HOW TO CAUSE A FILE DOWNLOAD

// REQUIRED FOR USE WITH THE PHP date() FUNCTIONS
date_default_timezone_set('America/New_York');

// A FILE TO DOWNLOAD - THIS LINK COULD COME IN THE URL VIA $_GET, OR COULD BE GENERATED INSIDE THE SCRIPT
//$url = "http://www.LAPRBass.com/piechart.png";
$url = "../dibsw2k-logo.gif";

// THE USE CASE FOR THE FUNCTION
force_download($url);



// FUNCTION TO FORCE A DOWNLOAD FROM A FILE
function force_download($filename)
{
    // GET THE CONTENTS OF THE FILE
    $filedata = file_get_contents($filename);

    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;
    }

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

Open in new window

Mukesh YadavFull Stack Developer

Commented:
Then confirm that you file exists or not?
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
Are you sure there is nothing wrong with your source image?

The code you works perfectly when I tested it on my own image.
Most Valuable Expert 2011
Top Expert 2016
Commented:
Can you view the file at the URL by typing its address into a browser window?  If so, my force-download script should be able to download it.  If not, there may be something wrong with the file or the file path.  

Please give us a little more to go on, like a public-facing URL of the file.  Once we have that we can experiment with it, and may be able to give you a tested and working example.

<?php // demo/force_download.php

/**
 * Show how to force a file download
 *
 * Choose a file to download, either via a hard-coded file path
 * or via a URL parameter like this
 *
 * path/to/demo/force_download.php?url=path/to/file.txt
 *
 * If you wanted to use the URL parameter, you might want to
 * (1) Secure the script with password protection
 * (2) replace the $url variable with something like this:
 * $url = $_GET['url'];
 *
 * If you use the URL parameter, be careful that the script
 * does not expose sensitive data on your server!
 */


// WHAT FILE DO WE WANT TO DOWNLOAD?
$url = "http://www.IcoNoun.com/demo/short_text_file.txt";


// USE CASE
force_download($url);



// FUNCTION TO FORCE A DOWNLOAD FROM A FILE
function force_download($url, $filename=NULL)
{
    // GET THE DOWNLOAD FILE NAME
    if (empty($filename)) $filename = basename($url);

    // GET LENGTH AND FILE RESOURCE POINTER
    $hdr = get_headers($url, TRUE);
    $len = trim($hdr['Content-Length']);
    $fpr = fopen($url,'rb');

    // ON SUCCESS
    if ($fpr)
    {
        // THESE HEADERS ARE USED ON ALL BROWSERS
        header("Content-Type: application-x/force-download");
        header("Content-Disposition: attachment; filename=$filename");
        header("Content-length: $len");
        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();

        // WRITE THE FILE
        fpassthru($fpr);
    }

    // ERROR
    else
    {
        trigger_error("ERROR: UNABLE TO OPEN $url", E_USER_ERROR);
    }
}

Open in new window

Dave BaldwinFixer of Problems
Most Valuable Expert 2014

Commented:
Ray, your script works fine to download image files too in the version I posted above.

Author

Commented:
My script downloads but the image will not display.

I run Ray's script above and it works.
Most Valuable Expert 2011
Top Expert 2016

Commented:
Dave, thanks.  I updated the older version recently and added better comments for my teaching library.  In most cases, either version would work correctly.

Author

Commented:
Sorry for the delay, and thanks again for your support and working code/answer.
Dave BaldwinFixer of Problems
Most Valuable Expert 2014

Commented:
You're welcome.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial