PHP+nginx完成大文件下載處理

最近在板子上做文件下載的處理,需求相對簡單,一個下載請求過來,根據請求的數據決定給那些文件回去,於是採用了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方式相對更安全一點。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章