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.
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');
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With