Take the 2-minute tour ×

I need to write a CSV file to the PHP output buffer and then download that file to the client's computer after it's done writing. (I wanted to just write it on the server and download it which was working, but it turns out I won't have write access on production servers).

I have the following PHP script:

$basic_info = fopen("php://output", 'w');
$basic_header = array(HEADER_ITEMS_IN_HERE);

@fputcsv($basic_info, $basic_header);

while($user_row = $get_users_stmt->fetch(PDO::FETCH_ASSOC)) {
    @fputcsv($basic_info, $user_row);


header('Content-Description: File Transfer');
header('Content-Disposition: attachment; filename=test.csv');
header('Expires: 0');
header('Pragma: public');
header('Content-Length: ' . filesize("php://output"));

I'm not sure what to do. The CSV file downloads but displays nothing. I assume it has something to do with the ordering of my ob_clean() and flush() commands, but I'm not sure what's the best way to order these things.

Any help is appreciated.

share|improve this question
If you write to the output buffer, you are immediately sending it to the client. In which case any headers need to be sent first. –  datasage Apr 2 '13 at 16:50
ob_clean() is pointless unless you've done an ob_start() somewhere. and consider that readfile WRITES to output, yet you're reading from that input. Unless you've done an ob_start() before all of this code, your fputcsv() have written to the output and gone to the browser BEFORE any of the header code even gets executed. –  Marc B Apr 2 '13 at 16:51
I can name literally one method in PHP whenever using of "@" can be justified. It's not in your code, so instead of planting @ on each line, you could write your code correctly at start? –  Marcin Orlowski Apr 2 '13 at 16:52
@WebnetMobile unserialize()? –  Mike B Apr 2 '13 at 16:52
@WebnetMobile my guess is mail(). –  Halcyon Apr 2 '13 at 16:54

1 Answer 1

up vote 5 down vote accepted

You're doing a little too much. Create the script with the sole purpose of outputting the CSV. Just print it out directly to the screen. Don't worry about headers or buffers or php://output or anything like that yet.

Once you've confirmed that you're printing the data out to the screen appropriately, just add these headers at the beginning:

header("Content-disposition: attachment; filename=test.csv");

... confirm that that downloads the file appropriately. Then you can add the other headers if you like (the headers I included above are those I've used myself without any extra cruft to get this working, the others are basically for efficiency and cache control, some of which may already be handled appropriately by your server, and may or may not be important for your particular application).

If you want, use output buffering with ob_start() and ob_get_clean() to get the output contents into a string which you can then use to fill out Content-Length.

share|improve this answer
thanks for actually helping me unlike others who just complain about things I'm doing wrong –  jrubins Apr 2 '13 at 17:11

Your Answer


