Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

File download in IE6 gets the wrong filename

I have a PHP script being served over https:// that is trying to push a PDF file to the user. The problem that in Internet Explorer 6 (which unfortunately I still have to support) is not obeying the filename being set in the header. FireFox and IE7 are both working properly.

The file name keeps coming out as a random name with the correct extension. Example: "CAOTC5K3.pdf", "CAXSIPXV.pdf" or "CA1OCVTX.pdf"

If I un-comment out the "Content-type" line, IE6 gives me an error, and tries to download the file inline with the name of the querystring that was passed to PHP.

<?php
//header( "Content-type: application/pdf" );
$filename = 'quickquote.pdf';
header( "Content-Disposition: attachment;filename=$filename" );
echo file_get_contents( "/example.pdf" );
die;
?>

I have tried wrapping the file name in quotes, adding a \n at the end of the header lines, adding header('Content-type: application/octet-stream');, adding header("Content-Type: application/force-download");

like image 251
bkulyk Avatar asked May 19 '10 20:05

bkulyk


1 Answers

I think you might need a space after attachment;:

header("Content-Disposition: attachment; filename=$filename");

If that doesn't work, check out some of the points in this article, including:

  • On IE 6.0, things mostly work, but if you ALSO setup Cache-Control: no-cache, your suggested filename (and type!) will be IGNORED. A bummer if you have to choose between security and convienence. Of course, security wins.
  • On nearly all versions of IE, including 6.0, sometimes the browser will use the filename in the address bar instead of the Content-Disposition Header, and with IE5.5SP2 you're expected to change the UseCDFileName registry key, see Q303750. This was fixed with IE6.0SP1.

EDIT: Here's the code I use, directly copied from my application's source. Let me know if this works any better...

function forceDownload($filename,$mime=false,$downloadName=false)
{
    if(file_exists($filename) && is_readable($filename))
    {
        if(!$mime)      $mime = DFStdLib::determineMimeType($filename);

        if(!$expire)    $expire = DFStdLib::HOUR_IN_SECONDS;

        if(!$downloadName) $downloadName = basename($filename);

        header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($filename)).' GMT', true, 200);
        header('Cache-Control: no-cache',true);
        header('Pragma: Public',true);
        header('Expires: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT',true);
        header('Content-Length: '.filesize($filename),true);
        header("Content-Type: {$mime}",true);
        header("Content-disposition: attachment; filename=$downloadName",true);
        readfile($filename);
        exit();
    }
    else
    {
        header('HTTP/1.1 404 Not Found',true,404);
        echo "<html><head><title>Not Found</title></head><body>The file was not found.</body></html>";
        exit();
    }
}

Usage for your case would be:

forceDownload('/example.pdf','application/pdf','quickquote.pdf');

Also you'll need to change DFStdLib::HOUR_IN_SECONDS to 3600 and write your own determineMimeType function, or delete that line and make the $mime argument required...

like image 105
Josh Avatar answered Oct 31 '22 02:10

Josh