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.
    – apaderno
    Commented Mar 21, 2011 at 17:09
  • About the possibility, the answer is yes. There are some modules that implement an export feature, including Views and CCK.
    – apaderno
    Commented Mar 21, 2011 at 17:12

2 Answers 2


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. Commented Mar 21, 2011 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.
    – apaderno
    Commented Mar 21, 2011 at 17:11
  • @Chris Cohen: There will be no redirect when a module calls exit() during the page callback.
    – Berdir
    Commented Mar 21, 2011 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. Commented Mar 21, 2011 at 17:30
  • @kiamlauno, Thanks for mentioning about module_invoke_all('exit'), will use it from now.
    – Sivaji
    Commented Mar 21, 2011 at 19:59

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;

(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 and acknowledge you have read our privacy policy.

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