0
votes

I know this question has been asked several times in here and I have used so many of the suggestions here but none of them work for me.

My Application first creates a list of Feeds and then the user select the feeds to export. The php file dynamically generates a csv file for each feed and adds them to the zip file. At the end I am just closing the zip file and reading it with readfile($zipfile).

When debugging it with FireBug in firefox the response headers are as expected and the response is also in binary format. But this will not generate the save dialog box on the browser.

Now if I take the URL for export and paste it directly onto a new window and click, the dialog box appears.

So what is missing here, why cannot the existing page generate the dialog box?

Here is my code.

public function export_feeds($start, $end, $feedIds)
    {
        // Name of the file to export
        $date = date('Y_m_j_H');
        $fileName = 'Feeds_'.$date.'.zip';

        // We create the ZIP file
        $zip = new ZipArchive;
        $result_zip = $zip->open($fileName, ZipArchive::CREATE);    // We open the file
        if ($result_zip === TRUE) {

            //iterate through each row of the feedId and find the engine. Call the export function from the specifi engine class and collect the data
            $feedIdsArry = explode(":",$feedIds);

            foreach ($feedIdsArry as $value) {

                $qresult = $this->mysqli->query("SELECT engine, name FROM feeds WHERE `id` = '$value'");
                $row = $qresult->fetch_array();

                if ($row['engine']==Engine::TIMESTORE) {

                    //$tableContent = $this->timestore->exportTable($value,$start,$end);
                    $tableContent = $this->mysqltimeseries->exportTable($value,$start,$end); //temporary workout
                    $tableContent = implode("\n", $tableContent);
                }
                if ($row['engine']==Engine::MYSQL) {

                    $tableContent = $this->mysqltimeseries->exportTable($value,$start,$end);
                    $tableContent = implode("\n", $tableContent);
                }

                $localFileName = $row['name'].'_'.$date.'.csv';
                $zip->addFromString($localFileName, $tableContent);
            }
            $zip->close();
        }
        else {
            echo 'Failed, code:' . $result_zip;
        }    

        header("Pragma: public");
        header("Expires: 0");
        header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
        header("Cache-Control: public");
        header("Content-Description: File Transfer");
        header("Content-type: application/zip");
        header("Content-Disposition: attachment; filename=".$fileName);
        header("Content-Transfer-Encoding: binary");
        header("Content-Length: ".filesize($fileName));

        if(!file_exists($fileName)) {
            die('Zip file not found');
        }
        else {
            readfile($fileName);  // To download the ZIP file
        }
        exit;

    } 

Here is the response headers from Firebug

Cache-Control   public
Connection  Keep-Alive
Content-Description File Transfer
Content-Disposition attachment; filename=Feeds_2013_10_24_14.zip
Content-Length  1600
Content-Type    application/force-download
Date    Thu, 24 Oct 2013 01:39:38 GMT
Expires 0
Keep-Alive  timeout=5, max=100
Pragma  public
Server  Apache/2.4.6 (Win32) PHP/5.5.4
X-Powered-By    PHP/5.5.4
content-transfer-encoding   binary
2
how are you linking to the download?Chase
There is no link to the zip file download, when clicking on Export button, this is code I call.Shankar

2 Answers

1
votes

Try using these headers:

Original Response

header('Cache-Control: public');  
header('Content-Description: File Transfer');  
header('Content-type: application/force-download');
header('Content-Disposition: attachment; filename="'.$filename.'"');

Update

You could also try using cURL instead of readfile(), something like:

function file_get_contents_curl($url) {
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //Set curl to return the data instead of printing it to the browser.
    curl_setopt($ch, CURLOPT_URL, $url);

    $data = curl_exec($ch);
    curl_close($ch);

    return $data;
}

Then:

if(!file_exists($fileName)) {
   die('Zip file not found');
}
else {
   $file_content = file_get_contents($fileName);  // To download the ZIP file
   header('Cache-Control: public');  
   header('Content-Description: File Transfer');  
   header('Content-type: application/force-download');
   header('Content-Disposition: attachment; filename="'.$filename.'"');
   echo $file_content;
}
exit;
0
votes

First make sure you didn't send some headers except for your download zip. I use another header:

        header('Content-Description: File Transfer');
        header('Content-type: application/zip');
        header('Content-Disposition: attachment; filename="'.($filename).'"');
        header("Content-Transfer-Encoding: binary");
        header('Expires: 0');
        echo($file_content);
        exit;

Maybe try to do two functions. One for create zip and the second one to download. You can add a pop-up with a button to download? When you click on the button you call the second function