views:

52

answers:

2

Hi guys,

So I am having this problem wit my download link. Basically my previous way of creating download link is to just have a form button with method='link' and the action to be the link to the file. This works for firefox and others but not safari. For some reason, when the user tries to download the file (excel file) from safari, it would just show bunch of ascii characters on the browser (I guess its trying to read it using the browser?). Well, I was looking for another solution and it seems like using header is the way to do it. So now I am tryng to create a form button with method='post' and action='download.php' where there is a hidden field with the link to the file. It looks like this

function showDownloadWithHeader($link){
    echo "<form action='download.php' method='post' >";
    echo "<input class='downloadButton' type='submit' value='Download Report'>";
    echo "<input type='hidden' name='filename' value='$link'>";
    echo "</form>";
}

And inside the download.php I would just want the user to be asked to download the file.

<?php
    if($_POST['filename'] == '' || empty($_POST['filename'])){
        exit;
    }

    $filename = $_POST['filename']; //the file is 2 folder down. e.g. data/stack/bla.xlsx
    $file = $filename;
    $extension = end(explode('.', $filename));
    error_reporting(E_ALL);
    ini_set("display_errors",1);
//  echo $filename;
//  echo "<br/>";
//  echo $extension;
//  echo filesize($filename);
//  echo "<br/>";
    switch($extension){
        case 'xls':
            $mimeType = 'application/vnd.ms-excel';
            break;
        case 'xlsx':
            $mimeType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
            break;
    }
//  echo $mimeType;
    header('Content-Description: File Transfer');
    header('Content-Type: ' . $mimeType);
    header('Content-Disposition: attachment; filename='.basename($file));
    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));
    ob_clean();
    flush();
    readfile($filename);
    exit;
?>

I saw this solution on php.net under readfile() function but it doesnt seem to be working for me. I am doing this on localhost.

+1  A: 

Something like this works fine.

header("Pragma: public", true);
header("Expires: 0"); // set expiration time
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Disposition: attachment; filename=".basename($file));
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($file));
die(file_get_contents($file));
Mitch C
what's application/force-download and application/download? they aren't valid common mime-types they might be used in some browsers/programs but not normally
Viper_Sb
you are my saviour!
denniss
They're likely browser specific headers. This script has been sitting in my library for some time - it hasn't failed me yet.
Mitch C
@Mitch C: For some reason your script only works for safari. when trying to open it using firefox, the script will try to safe the file without the excel extension.
denniss
header("Content-Disposition: attachment; filename=".basename($file).".csv");
Mitch C
Quote the filename filename="myfile.xlsx"
Viper_Sb
+1  A: 

If I understand you correctly the script is working as expected, i.e if a browser recognizes mime type:

'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'

Then it SHOWS it in browser (whether or not it displays correctly is something else)

Since you want to FORCE it to download INSTEAD OF showing in browser use the mime type:

'application/octet-stream'

This should work in all browsers and force the download instead of display in browser.

Viper_Sb