4

I have a FAPI form that collects some information from the user, then generates a CSV file. The intent is when the user clicks 'export' on the form, the CSV is downloaded straight away.

However, when the submit handler calls the CSV-generating function, the form just redirects, rather than serving the CSV.

Is there any way to make this form serve the CSV to the user directly, without generating a temporary file?

  • Can you show the code you are using for your form submission handler? Without it, I can only guess what happens. – kiamlaluno Mar 21 '11 at 17:09
  • About the possibility, the answer is yes. There are some modules that implement an export feature, including Views and CCK. – kiamlaluno Mar 21 '11 at 17:12
6

I guess the code in this blog post http://sirkitree.net/node/23 will help. Essentially you need to use exit() or die() at the end of your submit handler to prevent redirect.

  $file = $header ."\n";
  foreach ($accounts as $row) {
    $file .= $row ."\n";
  }
  header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
  header('Content-Type: text/csv');
  header('Content-Disposition: attachment; filename="users.csv"');
  die(print $file);
  
  • Thanks, but I think you've missed the point. I know how to print a CSV to the output. When doing this in a FAPI submit handler, the form redirects rather than serving the CSV. – Chris Cohen Mar 21 '11 at 16:56
  • 2
    A Drupal module should never call die(); if it would, it should call module_invoke_all('exit'), and then exit(). There are few cases where a module should call exit(), though. – kiamlaluno Mar 21 '11 at 17:11
  • @Chris Cohen: There will be no redirect when a module calls exit() during the page callback. – Berdir Mar 21 '11 at 17:23
  • Hmm that's interesting. Perhaps there is something else going on in my code, so I'll check that out and report back. – Chris Cohen Mar 21 '11 at 17:30
  • @kiamlauno, Thanks for mentioning about module_invoke_all('exit'), will use it from now. – Sivaji Mar 21 '11 at 19:59
2

The following routine will "push" a file to the user, causing the browser to pop a "save file" dialog:

function _cex_download( $output, $filename ) 
{
  header("Pragma: public");
  header("Expires: 0");
  header("Cache-Control: private");
  header("Content-type: application/octet-stream");
  header("Content-Disposition: attachment; filename=$filename");
  header("Accept-Ranges: bytes");
  echo $output;
  exit;
} 

(Where 'cex' is the name of my custom module, and '_cex' designates a private function.)

To use this, generate your CSV file inside a string, and then simply call this, passing in the CSV contents in $output and the filename the browser will be save it as in $filename.

I originally got this logic from how Ubercart handles secure downloads.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.