CSV files are handy ways of handing over long lists of data like transactions, audits, surveys or logs over to a user, particularly because they are so universally supported by just about all spreadsheet applications.

Normally when you want a user to download a file you simply force the browser to point to the location of the file you want them to download, however as we all know, this doesn’t always work as often the browser will decide what to do with the file – be it to display the file contents, redirect you to a particular browser plugin, or give you the choice as to whether you want to download the file or perhaps do something else with it.

Because CSV files are nothing more than plain text files, browsers often choose simply to open them up as text, pretty useless in that if forces the user to now look for the “save as” option in the browser’s menu system.

Luckily, the way to get around this and force a download is pretty common to most file types – all you do is set the necessary header information and then read the target file’s contents and push it straight to the browser via the output buffer.

So let us see this in action for a CSV file then:

header("Content-type: application/vnd.ms-excel");
header("Content-Disposition: attachment; filename=downloadrecords.csv");
readfile($_SERVER['DOCUMENT_ROOT'] . '/downloadrecords.csv');

In the above example we want the user to download /downloadrecords.csv. Now instead of directing a user directly to that path, we instead send them to a force download script, with sets the necessary headers like the all important content-disposition header, and then simply read the existing CSV file contents straight into the output buffer using the handy readfile function.

Flush the buffer and the browser will now do the rest.