The approach to generating and and triggering download dialog is incorrect. A dialog (download) cannot be initiated from a background process(AJAX call)
I am trying to create/download a CSV file on button click. When i simply try to create the CSV the code works fine as below:
Drupal button :
$form['Export'] = array(
'#type' => 'submit',
'#value' => t('Export'),
"#ajax" => array(
"callback" => "export_csv",
),
Processing code:
$out = fopen('filename.csv', 'w');
//processing to create file csv
fputcsv($out, $info, ";");
fclose($out);
the csv file is created and stored in the root directory.
However when i try to add headers the code below fails with ajax error and no debug info
$fichier = 'inscriptions.csv';
header( "Content-Type: text/csv;charset=utf-8" );
header( "Content-Disposition: attachment;filename=\"$fichier\"" );
header("Pragma: no-cache");
header("Expires: 0");
$out = fopen('php://output', 'w');
//processing to create file csv
fputcsv($out, $info, ";");
fclose($out);
As stated in @misorude comments - don't try to trigger download from background request, instead make it drupal way.
Lest assume you have my_export_module.
In hook_menu
//(...)
//export download csv
$items['export/download-csv'] = array(
'page callback' => 'my_export_module_download_csv',
'delivery callback' => 'my_export_module_deliver_csv',
'type' => MENU_CALLBACK,
);
In my_export_module_download_csv
function. Assume $input
is 2-dimensional array to export.
//(...)
//generate csv
//open tmp stream
$f = fopen('php://temp', 'w');
foreach ($input as $input_line) {
if (is_array($input_line)) {
fputcsv($f, $input_line, $delimiter);
}
}
fclose($f);
return array(
'name' => $output_file_name,
);
And in the end the my_export_module_deliver_csv
function
function my_export_module_deliver_csv($var = NULL) {
drupal_add_http_header('Content-Encoding', 'UTF-8');
drupal_add_http_header('Content-Type', 'application/csv;charset=UTF-8');
if (isset($var['name'])) {
drupal_add_http_header('Content-Disposition', 'attachment; filename="' . $var['name'] . '";');
}
if (isset($var['file'])) {
echo $var['file'];
}
}
This way file is not stored on server, but when entering export/download-csv it should trigger download.