-1

I am trying to export and download a csv file through php. I have done exactly what was suggested in Export to CSV via PHP

I can see my array dump in the response but the csv file is just not downloading. Please Help.

Here is my code:

function download_send_headers($filename) {
// disable caching
    $now = gmdate("D, d M Y H:i:s");
    header("Expires: Tue, 03 Jul 2001 06:00:00 GMT");
    header("Cache-Control: max-age=0, no-cache, must-revalidate, proxy-revalidate");
    header("Last-Modified: {$now} GMT");

// force download  
    Header('Content-Description: File Transfer');
    header("Content-Type: application/force-download");
    // header("Content-Type: application/octet-stream");
    // header("Content-Type: application/download");

 // disposition / encoding on response body
    header("Content-Disposition: attachment;filename={$filename}");
    header("Content-Transfer-Encoding: binary");
}

function array2csv(array &$array)
{
   //   if (count($array) == 0) {
  //     return null;
   //   }
        ob_start();
        $df = fopen("php://output", 'w');
        fputcsv($df, array_keys(reset($array)));
        foreach ($array as $row) {
           fputcsv($df, $row);
        }
        fclose($df);
        return ob_get_clean();
}

Here is how im using it:

download_send_headers("data_export_" . date("Y-m-d") . ".csv");
echo array2csv($modsucc);
die();
Community
  • 1
  • 1
Sanidhya
  • 31
  • 1
  • 7

3 Answers3

1

This is javascript function:

function exporttocsv(filter){


      var fd = new FormData();
      fd.append('filter', filter);
      fd.append("form", "export_to_csv");
      $.ajax({
        url: getBaseURL()+'assets/handler/OrderManagementHandler.php',
        type: 'POST',   
        data: fd,
        enctype: 'multipart/form-data',
        processData: false, 
        contentType: false,
      })
      .done(function(res) {

        })
        .fail(function() {

        });
}

Handler:

case 'export_to_csv':

    $controller->exportToCSV($_POST);
    break;

Controller:

public function exportToCSV($data){

    $filter = $data['filter'];

    $mod = new OrderManagementModel();
    $modsucc = $mod->exportToCSV($filter);

    if($modsucc){

       // var_dump(ini_get('output_buffering'));
        //var_dump($modsucc);
        download_send_headers("data_export_" . date("Y-m-d") . ".csv");
        echo array2csv($modsucc);
        die();
    }
}
Sanidhya
  • 31
  • 1
  • 7
1

Your code not work because you use ajax and you cant download files with ajax itself, simple way is this:

...
if($modsucc){
    $file = /* directory */"data_export_" . date("Y-m-d") . ".csv";

    $df = fopen(file, 'w');
    fputcsv($df, array_keys(reset($array)));
    foreach ($array as $row) {
        fputcsv($df, $row);
    }
    fclose($df);

    echo $file;
}
...

this will save file, and in your ajax done function:

window.open(res);

this will open new window with address to previously saved file or

window.location.href = res;

this will redirect you to address where the file was saved

to force download you could do it like this:

//force-download.php
if(file_exists($_GET['file'])){
    download_send_headers("data_export_" . date("Y-m-d") . ".csv");
    echo file_get_contents($_GET['file']); // warning: unsafe !! session for example will be better
}

this will send headers for force download and read data from disk where data was previosly saved and echo them

and in your ajax done function:

window.open('force-download.php?file=' + res);

or

window.location.href = 'force-download.php?file=' + res;

this use address where force download headers will be sent

Another possibility is, change $_POST to $_GET and instead of using ajax just redirect to url and it will work with your old code

Kazz
  • 1,030
  • 8
  • 16
  • Thanks a lot....You are a life saver..I am newbie in web programming..learned a lot today..thanks a lot again.. – Sanidhya Oct 17 '16 at 21:14
0

Your code work, only think what could be wrong is if your server dont have enabled output buffering and you output something before calling function download_send_headers

Kazz
  • 1,030
  • 8
  • 16
  • output buffering is enabled – Sanidhya Oct 17 '16 at 07:19
  • does it depends on the buffer size of output buffering?..currently its default that is 4kb – Sanidhya Oct 17 '16 at 07:22
  • @Sanidhya yes, if you reach the limit, output is flushed out and you cant set headers anymore. Just send headers as soon as possible before any text. – Kazz Oct 17 '16 at 12:01
  • ok..but the headers are getting set everytime. I can see it in the network response headers. is it possible that because of the small buffer size, it is not able to hold the csv data and getting flushed out? – Sanidhya Oct 17 '16 at 13:51
  • when buffer is full then data are sent to client and buffer emptied ready to hold next data and again, so no... content type: `application/force-download` is unknown and browser will handle this content type as `application/octet-stream`, like `application/whatever-new-type` which is currently unknown – Kazz Oct 17 '16 at 14:13
  • but i test your code in firefox and chrome and it works as expected so i dont know where the problem is – Kazz Oct 17 '16 at 14:16
  • headers could be set only in first part of data which are sent to the client, and if you can see that the headers are properly set then browser didn't handle them properly – Kazz Oct 17 '16 at 14:25
  • try another browser and if not work as well then post full code – Kazz Oct 17 '16 at 15:18
  • Ok i am posting my full code below. Please check once. It didnt work with firefox and safari as well. – Sanidhya Oct 17 '16 at 18:43
  • please check, i have posted the code as an answer above – Sanidhya Oct 17 '16 at 18:47
  • This is the response header: Cache-Control:max-age=0, no-cache, must-revalidate, proxy-revalidate Connection:Keep-Alive Content-Description:File Transfer Content-Disposition:attachment;filename=data_export_2016-10-18.csv Content-Encoding:gzip Content-Length:62 Content-Transfer-Encoding:binary Content-Type:application/force-download Date:Mon, 17 Oct 2016 18:49:21 GMT Expires:Tue, 03 Jul 2001 06:00:00 GMT Keep-Alive:timeout=5, max=100 Last-Modified:Mon, 17 Oct 2016 18:49:21 GMT Pragma:no-cache Server:Apache/2.4.18 (Ubuntu) Vary:Accept-Encoding – Sanidhya Oct 17 '16 at 18:51