download files by simply having the URL point to a file located under document root.
But, doing so, there is no way to do some statistics, permission checks, etc. work. So, a lot of times, we use the PHP to do forwarding, for users to provide file downloads .
$file = "/tmp/dummy.tar.gz";
Header ("Content-type:application/octet-stream");
Header (' Content-disposition:attachment filename= '. basename ($file). ' "');
Header (" Content-length: "). FileSize ($file));
ReadFile ($file);
But there is a problem, if the file is a Chinese name, some users may download the file name is garbled.
So, let's make changes (reference::
$file = "/tmp/Chinese name. tar.gz";
$filename = basename ($file);
Header ("Content-type:application/octet-stream");
//process Chinese file name
$ua = $_server["Http_user_agent"] ;
$encoded _filename = UrlEncode ($filename);
$encoded _filename = str_replace ("+", "%20", $encoded _filename);
if (Preg_match ("/msie/", $ua)) {
header (' Content-disposition:attachment; filename= “' . $encoded _filename. ' "');
} else if (Preg_match ("/firefox/", $ua)) {
Header (content-disposition:attachment filename*= "UTF8") $filename. ' "');
} else {
header (' Content-disposition:attachment filename= '. $filename. ' "');
}
header (' Content-disposition:attachment filename= '. $filename. ' "');
Header (" Content-length: "). FileSize ($file));
ReadFile ($file);
Output, if it is Apache + PHP mod, then you need to send to Apache's output buffer. Last sent to the user. For Nginx + FPM, if they were deployed separately, it would also bring in additional network IO.
Well, it looks a lot better now, but there's a problem, that's ReadFile, though PHP's ReadFile try to be as efficient as possible, without consuming PHP's own memory, But in fact it still needs to use MMAP (if supported), or a fixed buffer to iterate through the file, direct output.
Today, I saw an interesting article: how I php:x-sendfile.
We can use the Apache module Mod_xsendfile to have Apache send this file directly to the user:
$file = "/tmp/Chinese name. tar.gz";
$ filename = basename ($file);
Header ("Content-type:application/octet-stream");
//handling Chinese file name
$ua = $_server["Http_user_agent"];
$encoded _filename = UrlEncode ($filename);
$encoded _ filename = str_replace ("+", "%20", $encoded _filename);
if (Preg_match ("/msie/", $ua)) {
header (' C Ontent-disposition:attachment filename= "'. $encoded _filename. ' "');
} else if (Preg_match ("/firefox/", $ua)) {
header (" Content-disposition:attachment Filenam e*= "UTF8 '". $filename. ' "');
} else {
header (' Content-disposition:attachment filename= '. $filename. ' "');
}
header (' Content-disposition:attachment filename= '. basename ($file). ' "');
//Let xsendfile send files
Header ("X-sendfile: $file");
Lighttpd and Nginx have similar modules that you can look for. The X-sendfile header will be processed by Apache and send the response file directly to the client.