Create and download a text file using php

Jhorra picture Jhorra · Jun 15, 2012 · Viewed 18.3k times · Source

Here's what I'm trying to do. I have a series of reports that they also want to be able to download as comma delimited text files. I've read over a bunch of pages where people say simply echo out the results rather than creating a file, but when I try that it just outputs to the page they are on.

I have this in the form of each report

Export File<input type="checkbox" name="export" value="1" />

So on the post I can check if they are trying to export the file. If they are I was trying to do this:

if($_POST['export'] == '1')
{
    $filename = date("Instructors by DOB - ".$month) . '.txt';

    $content = "";

    # Titlte of the CSV
    $content = "Name,Address,City,State,Zip,DOB\n";

    for($i=0;$i<count($instructors);$i++)
        $content .= ""; //fill content

    fwrite($filename, $content);

    header("Cache-Control: public");
    header("Content-Description: File Transfer");
    header("Content-Length: ". filesize("$filename").";");
    header("Content-Disposition: attachment; filename=$filename");
    header("Content-Type: application/octet-stream; "); 
    header("Content-Transfer-Encoding: binary");

    readfile($filename);
}

Basically the page refreshes, but no file is pushed for download. Can anyone point out what I'm missing?

EDIT I think I wasn't entirely clear. This is not on a page that only creates and downloads the file, this is on a page that is also displaying the report. So when I put an exit(); after the readfile the rest of the page loads blank. I need to display the report on this page as well. I think this could also have to do with why it's not download, because this page has already sent header information.

Answer

UltraInstinct picture UltraInstinct · Jun 15, 2012

I overlooked the way you are writing out the contents before asking you to try closing the file.

Check the fwrite manual here: http://php.net/manual/en/function.fwrite.php

What you need to do is:

$filename = "yourfile.txt";
#...
$f = fopen($filename, 'w');
fwrite($f, $content);
fclose($f);

and after closing the file, you can now safely send it across for download.

header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Length: ". filesize("$filename").";");
header("Content-Disposition: attachment; filename=$filename");
header("Content-Type: application/octet-stream; "); 
header("Content-Transfer-Encoding: binary");

readfile($filename);

There are a couple of things:

  • You really dont need to set the content-type as application/octet-stream. Why not set a more real type as text/plain?
  • I really dont understand how you want to use the date functionality. please refer to the manual here: http://php.net/manual/en/function.date.php
  • As correctly pointed out by @nickb, you must exit the script after doing the readfile(..)