Force file download with php using header()

PhpHttp Headers

Php Problem Overview


I want the user to be able to download some files I have on my server, but when I try to use any of the many examples of this around the internet nothing seems to work for me. I've tried code like this:

<?php

$size = filesize("Image.png");

header('Content-Description: File Transfer');
header('Content-Type: image/png');
header('Content-Disposition: attachment; filename="Image.png"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . $size);
readfile("Image.png");

I've even tried to use the most basic example I could find, like this:

<?php
header('Content-type: image/png');
header('Content-Disposition: attachment; filename="Image.png"');
readfile('Image.png');

When I've tested this I have removed all the other code I have and used an empty file with just this code to remove any faults created by external sources.

When I look in the console the file gets sent with the right headers i.e

'Content-Disposition: attachment; filename="Image.png"'

But the save dialog isn't displayed.

I've also tried with inline instead of attachment in the content disposition header but that didn't make a difference either, I've tested this in Firefox 8.0.1 Chrome 15.0.874.121 and Safari 5.1.1.

Php Solutions


Solution 1 - Php

I’m pretty sure you don’t add the mime type as a JPEG on file downloads:

header('Content-Type: image/png');

These headers have never failed me:

$quoted = sprintf('"%s"', addcslashes(basename($file), '"\\'));
$size   = filesize($file);

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . $quoted); 
header('Content-Transfer-Encoding: binary');
header('Connection: Keep-Alive');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . $size);

Solution 2 - Php

This worked for me like a charm for downloading PNG and PDF.

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.$file_name.'"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file_url)); //Absolute URL
ob_clean();
flush();
readfile($file_url); //Absolute URL
exit();

Solution 3 - Php

Based on Farhan Sahibole's answer:

        header('Content-Disposition: attachment; filename=Image.png');
        header('Content-Type: application/octet-stream'); // Downloading on Android might fail without this
        ob_clean();

        readfile($file);

This is all I needed for this to work. I stripped off anything that isn't required for this to work.

Key is to use ob_clean();

Solution 4 - Php

The problem was that I used ajax to post the message to the server, when I used a direct link to download the file everything worked fine.

I used this other Stackoverflow Q&A material instead, it worked great for me:

Solution 5 - Php

its work for me

$attachment_location = "filePath";
if (file_exists($attachment_location)) {

    header($_SERVER["SERVER_PROTOCOL"] . " 200 OK");
    header("Cache-Control: public"); // needed for internet explorer
    header("Content-Type: application/zip");
    header("Content-Transfer-Encoding: Binary");
    header("Content-Length:".filesize($attachment_location));
    header("Content-Disposition: attachment; filename=filePath");
    readfile($attachment_location);
    die();
} else {
    die("Error: File not found.");
}

Solution 6 - Php

the htaccess solution

<filesmatch "\.(?i:doc|odf|pdf|cer|txt)$">
  Header set Content-Disposition attachment
</FilesMatch>

you can read this page: https://www.techmesto.com/force-files-to-download-using-htaccess/

Solution 7 - Php

Here is a snippet from me in testing... obviously passing via get to the script may not be the best... should post or just send an id and grab guid from db... anyhow.. this worked. I take the URL and convert it to a path.

// Initialize a file URL to the variable
$file = $_GET['url'];
$file = str_replace(Polepluginforrvms_Plugin::$install_url, $DOC_ROOT.'/pole-permitter/', $file );

$quoted = sprintf('"%s"', addcslashes(basename($file), '"\\'));
$size   = filesize($file);

header( "Content-type: application/octet-stream" );
header( "Content-Disposition: attachment; filename={$quoted}" );
header( "Content-length: " . $size );
header( "Pragma: no-cache" );
header( "Expires: 0" );
readfile( "{$file}" );

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKerpView Question on Stackoverflow
Solution 1 - PhpLawrence CheroneView Answer on Stackoverflow
Solution 2 - PhpFarhan SahiboleView Answer on Stackoverflow
Solution 3 - PhpRobin van den HurkView Answer on Stackoverflow
Solution 4 - PhpKerpView Answer on Stackoverflow
Solution 5 - PhpMhmdView Answer on Stackoverflow
Solution 6 - PhpAli EmadzadehView Answer on Stackoverflow
Solution 7 - PhpRobert Ruby IIView Answer on Stackoverflow