Reputation: 2198
On LAMP stack, I can not get xSendFile to work. The problem is that the downloads have 0 bytes.
In order to be sure that I have xSendFile installed, I have added this to my .htaccess
file:
<IfModule mod_xsendfile.c>
SetEnv MOD_mod_xsendfile 1
</IfModule>
(I can not test this with apache_get_modules()
because I am running PHP as fastCGI.)
I then have the following PHP code:
if (1 != getenv('MOD_mod_xsendfile'))
{
echo 'mod_xsendfile is not installed';
}
else
{
$path = '/home/infar/';
$file = 'hello.txt';
if (file_exists($path.$file) && strlen($path.$file)>1)
{
if (true) // change to false to go around Yii
{
Yii::app()->request->xSendFile($path.$file,array(
'saveName'=> 'hello.txt',
'mimeType'=> 'plain/text',
'terminate'=> true,
));
}
else
{
//set proper Content-Type
header('Content-Type: plain/text');
//force download box with the filename hello.txt
header('Content-Disposition: attachment;filename=hello.txt');
header('X-Sendfile: $path.$file');
exit;
}
}
else
{
echo 'file not found at: '.$path.$file;
}
}
This code runs as expected; from which I conclude that xSendFile must be installed and/or enabled. I then run this script both with Yii xSendFile
and with plain PHP. In both cases the download window opens, but always with 0 bytes.
I am at my wits' end. What am I doing wrong?
In the interest of full disclosure, here is the relevant part of httpd.conf
:
<IfModule mod_xsendfile.c>
XSendFile on
XSendFilePath /home/infar
</IfModule>
Edit:
Output compression is turned off:
ini_get("zlib.output_compression"); // returns "Off"
Chrome shows me the following headers:
Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection:Keep-Alive
Content-Disposition:attachment;filename=hello.txt
Content-Length:0
Content-Type:plain/text
Date:Sun, 23 Mar 2014 18:22:49 GMT
Expires:Thu, 19 Nov 1981 08:52:00 GMT
Keep-Alive:timeout=2, max=100
Pragma:no-cache
Server:Apache
X-Sendfile:/home/infar/hello.txt
Update March 26th, 2014
When testing @gabrieloliveira suggestion, I discovered the following:
header('Content-Type: plain/text');
header('Content-Disposition: attachment;filename=hello.txt');
header('X-Sendfile: '.$path.$file); // $path.$file outside quotes
header('Content-Length: '.filesize($path.$file)); // Filesize
echo '12345678901234567890';
exit;
This script (where I have added echo '12345678901234567890';
) produced a download for a file containing the following 16 character string 1234567890123456
. 16 characters matches the filesize of hello.txt
. So it seems we can conclude the following
In fact, commenting out X-SendFile, like so:
// header('X-Sendfile: '.$path.$file);
produces the same result; indiscernible from executing the X-Sendfile
header.
Upvotes: 5
Views: 4112
Reputation: 570
Test with pure PHP editing this part:
header('Content-Type: plain/text');
//force download box with the filename hello.txt
header('Content-Disposition: attachment;filename=hello.txt');
header('X-Sendfile: '.$path.$file); // $path.$file outside quotes
header('Content-Length: '.filesize($path.$file)); // Filesize
Edit:
Try change:
header('application/octet-stream');
Upvotes: 3
Reputation: 6938
Make sure the path to the file to serve is the same path you're using on the XSendFilePath
directive on httpd.conf
or httpd-vhosts.conf
Or: Are you sending files which are outside the public folder? If so then add XSendFileAllowAbove on to apache config
Upvotes: 2