最近在板子上做文件下載的處理,需求相對簡單,一個下載請求過來,根據請求的數據決定給那些文件回去,於是採用了php+nginx的方式來處理。
嘗試
nginx用來處理下載請求,拿到請求以後,調用配置好的php文件,php文件中對請求的參數做處理。nginx的配置:
server{
listen 8080;
server_name xxxxx.com;
index index.html index.htm index.php;
location / {
try_files $uri $uri/ /index.php?path=$uri&$args;
}
location ~ .*\.(cgi|php|php5)?$ {
root /www/test;
include fastcgi.conf;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass 127.0.0.1:8008;
}
}
php裏面也不麻煩:
//通過請求參數提取出實際的文件名
$fileName = xxxx
if(file_exists($fileName)){
$file = fopen ($fileName, "rb" );
$filesize = filesize ($fileName);
//讀取文件內容並返回給請求接口
echo fread ( $file, filesize ( $fileName) );
fclose ( $file );
exit(0);
}else{
.......
}
但是這樣會有一個問題,只是小文件的時候纔可以,一旦文件過大,php會掛掉,因爲這是讀到了內存裏面,請求多了內存就被耗光了,如果追求響應速度,並且優化內存的使用,是可以這麼幹,但我這次的需求顯然不是這樣,所以考慮php分析完文件下載的參數後,能否將下載請求交回給nginx來負責,這是可以的,有兩種方式:
1 X-Accel-Redirect方式
2 Location方式
Redirect方式
nginx的配置如下:
server{
listen 8080;
server_name xxxxx.com;
index index.html index.htm index.php;
location / {
try_files $uri $uri/ /index.php?path=$uri&$args;
}
location /download/ {
internal;
root /download/mp4/;
}
location ~ .*\.(cgi|php|php5)?$ {
root /www/test;
include fastcgi.conf;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass 127.0.0.1:8008;
}
}
php文件
//通過請求參數提取出實際的文件名
$fileName = xxxx
if(file_exists($fileName)){
header( "Content-Type: application/octet-stream" );
header( "X-Accel-Redirect: /download/".$fileName);
exit(0);
}else{
.......
}
Location方式
本地的nginx再多配置一個域名就可以了,比如多配置一個download.xxxx.com
nginx配置有兩個,一是接受第一次下載請求的(8080端口的域名),二是接受跳轉到本地的請求的(8088端口域名):
server{
listen 8080;
server_name xxxxx.com;
index index.html index.htm index.php;
location / {
try_files $uri $uri/ /index.php?path=$uri&$args;
}
location ~ .*\.(cgi|php|php5)?$ {
root /www/test;
include fastcgi.conf;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass 127.0.0.1:8008;
}
}
本地下載的nginx配置:
server{
listen 8088;
server_name download.xxxxx.com;
index index.html index.htm index.php;
root /download/mp4;
location / {
expires 30d;
}
}
php文件
$fileName = xxxx
if(file_exists($fileName)){
header( "Location: http://download.xxxxx.com/" );
exit(0);
}else{
.......
}
注意
Location這種方式下,通過這個download.xxxxx.com域名,其他人也是可以下載到這個文件的,相當於多了一種訪問本地文件的途徑。但是,Redirect方式這種方式,只能通過xxxx.com這個域名下載文件。Redirect方式相對更安全一點。