PHP - Force file to download - not working

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

keith1001Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Mukesh YadavFull Stack DeveloperCommented:
Remove line 7.

File is not downloading because you are saying browser that connection is closed. After receiving this header browser closes connection.
0
keith1001Author 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.
0
Mukesh YadavFull Stack DeveloperCommented:
Means you are getting file smaller than it is actually?
0
Cloud Class® Course: MCSA MCSE Windows Server 2012

This course teaches how to install and configure Windows Server 2012 R2.  It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

Dave BaldwinFixer of ProblemsCommented:
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

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Mukesh YadavFull Stack DeveloperCommented:
Then confirm that you file exists or not?
0
Julian HansenCommented:
Are you sure there is nothing wrong with your source image?

The code you works perfectly when I tested it on my own image.
0
Ray PaseurCommented:
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

0
Dave BaldwinFixer of ProblemsCommented:
Ray, your script works fine to download image files too in the version I posted above.
0
keith1001Author Commented:
My script downloads but the image will not display.

I run Ray's script above and it works.
0
Ray PaseurCommented:
Dave, thanks.  I updated the older version recently and added better comments for my teaching library.  In most cases, either version would work correctly.
0
keith1001Author Commented:
Sorry for the delay, and thanks again for your support and working code/answer.
0
Dave BaldwinFixer of ProblemsCommented:
You're welcome.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.