blandau
blandau

Reputation: 80

Force download file with PHP giving empty file

The end goal is for the user to download a .csv file. Right now I'm just testing trying to download a simple text file: test.txt. The only thing in this file is the word "test".

Here is the HTML code for files_to_download.php

Test file: <a href='test.php?file=test.txt'>Test.txt</a>

Code for test.php:

if(!(empty($_GET["file"])))
{
    $file_name = $_GET["file"];
    $path = "path/to/file";
    $fullPath = $path . $file_name;

    if(ini_get('zlib.output_compression'))
      ini_set('zlib.output_compression', 'Off');

    header("Cache-Control: public");
    header("Content-Description: File Transfer");
    header("Content-Disposition: inline; attachment; filename=\"$file_name\"");
    header("Content-Type: text/plain");
    header("Content-Transfer-Encoding: binary");
    readfile($fullPath);
}

I've tried variations of the headers above, adding more and removing others. The above seem to be the most common recommended on this site.

I've also tried changing

header("Content-Type: text/plain");

to

header("Content-Type: text/csv");

and get same results: empty .txt or .csv file.

The files are not empty when I open them directly (file browser) from the server. I've checked the permissions of the files and they're both 644, so the entire world can at least read the files. The directory is 777.

Is there a configuration on the Apache server I need to specify that may not be or am I missing something above.

Thanks for looking!

Upvotes: 1

Views: 11899

Answers (4)

Fenix Aoras
Fenix Aoras

Reputation: 241

In my case, the path was correct. And the download-forcing was working on windows, but not mac.

I figured out after few tests that the header Content-Length was failing. I was using the function filesize on a full url, like :

$url_my_file = "http://my-website.com/folders/file.ext";
header('Content-Length: '.(filesize($url_my_file)));

I replace it by

$url_my_file = "http://my-website.com/folders/file.ext";    
$headers  = get_headers($url_my_file, 1);
header('Content-Length: '.($headers['Content-Length']));

And ... It's working now :)

Upvotes: 1

aWebDeveloper
aWebDeveloper

Reputation: 38422

In most cases the path is wrong

Upvotes: 9

Leon
Leon

Reputation: 869

Try setting the content length of the file:

header('Content-Length: ' . filesize($file));

Also, please have this in mind: file inclusion

Upvotes: 1

Calvin
Calvin

Reputation: 8775

Read the text file, then echo the text out after your header() calls.

Here's how I have my csv download set up:

//downloads an export of the user DB
$csv = User::exportUsers();

header('Content-disposition: attachment; filename=userdb.csv');
header('Content-type: text/csv');

echo $csv;

Where exportUsers() creates the csv data. You can easily just replace $csv with the contents of your text file, then echo it out.

And as far as your text file, you can use file_get_contents() to get the contents of your file into a string. Then echo that string.

Upvotes: 1

Related Questions