在實現文件下載功能時通常有以下幾種方式:
1.直接給出下載地址,例如http://****.com/test/test.rar,這種是最直接的方式,任何人都可以下載,無法控制用戶的權限。
2.驗證權限后通過PHP來讀取文件內容,示例代碼:
//發送header前首先驗證權限
header("Content-Type:application/octet-stream;charset=utf-8");
header('Content-Disposition: attachment; filename=test.rar');
readfile('./test/test.rar');
這樣做可以實現權限的控制,但是這個過程是PHP進程將文件讀取到內存中然后再發送給用戶,這樣造成很大的資源開銷,如果你文件較大,可能會超時,並且會占用比較大的內存,當用戶下載量很大時有可能造成PHP程序的崩潰。
3.這也是重點介紹的X-Sendfile,X-Sendfile 是一種將文件下載請求由后端應用轉交給前端 web 服務器處理的機制,它可以消除后端程序既要讀文件又要處理發送的壓力,從而顯著提高服務器效率,特別是處理大文件下載的情形下。
X-Sendfile 通過 HTTP header 來實現:在 X-Sendfile 頭中指定一個文件的地址來通告前web server。
不過,在默認情況下它是被大多數 web 服務器禁用的。而不同的 web 服務器的實現也不一樣,包括規定了不同的 X-Sendfile 頭格式。如果配置不合理將無法完成文件下載。
不同的 web 服務器實現了不同的 HTTP 頭 ,sendfile 頭和使用的 web 服務器如下:
X-Sendfile Apache, Lighttpd v1.5, Cherokee
X-LIGHTTPD-send-file Lighttpd v1.4
X-Accel-Redirect Nginx, Cherokee
使用 X-SendFile 的缺點是你失去了對文件傳輸機制的控制。例如如果你希望在完成文件下載后執行某些操作,比如只允許用戶下載文件一次,這個 X-Sendfile 是沒法做到的,因為后台的 php 腳本並不知道下載是否成功。
Nginx 默認支持該特性,不需要加載額外的模塊。只需要在配置文件中加入類似如下代碼;
location /protected/ {
internal;
root /file/soft;
}
internal 表示這個路徑只能在 Nginx 內部訪問,不能用瀏覽器直接訪問防止未授權的下載。
配置文件生效后,使用如下代碼即可實現下載:
//發送header前首先驗證權限
header("Content-Type:application/octet-stream;charset=utf-8");
header('Content-Disposition: attachment; filename=test.rar');
header('X-Accel-Redirect: /protected/www.rar');
以上代碼可以完成下載文件/file/soft/protected/www.rar