摘要:主要用于存儲速度不同步的設備或者優先級不同的設備之間傳辦理數據的區域。機制,意味在之前,建立了一新的隊列,數據必須經過該隊列。當需要下載的文件很大的時候,這種方式將消耗大量內存,甚至引發進程超時或崩潰,接下來就使用到。
一、普通文件下載
①laravel框架HTTP響應的download方法
$pathToFile = "myfile.csv";//參數一:絕對路徑 $downloadName = "downloadFile.csv";//參數二:下載后的文件名 //download 參數三:HTTP頭信息 return response()->download($pathToFile, $downloadName);
②PHP實現
$pathToFile = "myfile.csv";//文件絕對路徑 $downloadName = "downloadFile.csv";//下載后的文件名 //輸入文件標簽 Header("Content-type: application/octet-stream"); Header("Accept-Ranges: bytes"); Header("Accept-Length: " . filesize($pathToFile)); Header("Content-Disposition: filename=" . $downloadName); //輸出文件內容 $file = fopen($pathToFile, "r"); echo fread($file, filesize($pathToFile)); fclose($file); //或 //readfile($pathToFile);
其中fread()與readfile()的區別可以參考https://segmentfault.com/q/10...
但是有時候為了節省帶寬,避免瞬時流量過大而造成網絡堵塞,就要考慮下載限速的問題
$pathToFile = "myfile.csv";//文件絕對路徑 $downloadName = "downloadFile.csv";//下載后的文件名 $download_rate = 30;// 設置下載速率(30 kb/s) if (file_exists($pathToFile) && is_file($pathToFile)) { header("Cache-control: private");// 發送 headers header("Content-Type: application/octet-stream"); header("Content-Length: " . filesize($pathToFile)); header("Content-Disposition: filename=" . $downloadName); flush();// 刷新內容 $file = fopen($pathToFile, "r"); while (!feof($file)) { print fread($file, round($download_rate * 1024));// 發送當前部分文件給瀏覽者 flush();// flush 內容輸出到瀏覽器端 sleep(1);// 終端1秒后繼續 } fclose($file);// 關閉文件流 } else { abort(500, "文件" . $pathToFile . "不存在"); }
此時出現一個問題,當$download_rate>1kb時,文件正常下載;當$download_rate<1kb時,文件要等一會兒才下載,究其原因是因為buffer的問題。
buffer是一個內存地址空間,Linux系統默認大小一般為4096(1kb),即一個內存頁。主要用于存儲速度不同步的設備或者優先級不同的設備之間傳辦理數據的區域。舉個例子,你打開文本編輯器編輯一個文件的時候,你每輸入一個字符,操作系統并不會立即把這個字符直接寫入到磁盤,而是先寫入到buffer,當寫滿了一個buffer的時候,才會把buffer中的數據寫入磁盤。同樣的道理,當執行echo,print的時候,輸出并沒有立即通過tcp傳給客戶端瀏覽器顯示,而是將數據寫入php buffer。php output_buffering機制,意味在tcp buffer之前,建立了一新的隊列,數據必須經過該隊列。當一個php buffer寫滿的時候,腳本進程會將php buffer中的輸出數據交給系統內核交由tcp傳給瀏覽器顯示。所以,數據會依次寫到這幾個地方echo/pring -> php buffer -> tcp buffer -> browser。資料:http://blog.csdn.net/superhos...
在沒有開啟緩存時,腳本輸出的內容都在服務器端處于等待輸出的狀態,flush()可以將等待輸出的內容立即發送到客戶端。
開啟緩存后,腳本輸出的內容存入了輸出緩存中,這時沒有處于等待輸出狀態的內容,你直接使用flush()不會向客戶端發出任何內容。而ob_flush()的作用就是將本來存在輸出緩存中的內容取出來,設置為等待輸出狀態,但不會直接發送到客戶端,這時你就需要先使用ob_flush()再使用flush(),客戶端才能立即獲得腳本的輸出。
以及這篇文章同樣講述了ob_flush()和flush()的區別http://www.laruence.com/2010/...
但是這種方法將文件內容從磁盤經過一個固定的 buffer 去循環讀取到內存,再發送給前端 web 服務器,最后才到達用戶。當需要下載的文件很大的時候,這種方式將消耗大量內存,甚至引發 php 進程超時或崩潰,接下來就使用到X-Sendfile。
三、X-SendfileX-Sendfile 是一種將文件下載請求由后端應用轉交給前端 web
服務器處理的機制,它可以消除后端程序既要讀文件又要處理發送的壓力,從而顯著提高服務器效率,特別是處理大文件下載的情形下。
我是用的nginx,所以apache請參考https://tn123.org/mod_xsendfile/
①首先在配置文件中添加
location /download/ { internal; root /some/path;//絕對路徑 }
internal 表示這個路徑只能在 Nginx 內部訪問,不能用瀏覽器直接訪問防止未授權的下載
注意添加在location / {...}的前面
這樣你在代碼中使用時,文件路徑就可以寫成“/download/myfile.csv”
②重啟Nginx,寫代碼
$pathToFile = "myfile.csv";//文件絕對路徑 $downloadName = "downloadFile.csv";//下載后的文件名 $download_rate = 30;// 設置下載速率(30 kb/s) if (file_exists($pathToFile) && is_file($pathToFile)) { return (new Response())->withHeaders([ "Content-Type" => "application/octet-stream", "Content-Disposition" => "attachment;filename=" . $downloadName, "X-Accel-Redirect" => $pathToFile,//讓Xsendfile發送文件 "X-Sendfile" => $pathToFile, "X-Accel-Limit-Rate" => $download_rate, ]); }else { abort(500, "文件" . $pathToFile . "不存在"); }
如果你還想了解更多關于X-sendfile,請自行查閱
記得關注我呦
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/26165.html
摘要:簡述交互主要分為請求和響應兩種方式。狀態碼構建響應時,最先應做的是標識請求是否成功處理的狀態,可通過設置屬性,該屬性使用一個有效的狀態碼。 簡述 HTTP交互主要分為 request(請求) 和 response(響應) 兩種方式。 對于Yii2來說,HTTP的request請求是用 YII::$app->request 來表示的對象,這是Yii提供的處理HTTP的request請求的...
摘要:但是,你的連接數限制配置為允許單個連接數,單個連接數最大帶寬為。就降低單個連接數帶寬吧要知道大家誰沒事會用瀏覽器自帶下載器下載呢注本文只探討限速模塊在不同業務下的限速彩蛋偶爾發現,將連接數限制為迅雷不能高速下載了。 nginx 內置模塊限速怎么使用就不多說了,今天來說說連接數和單個連接數限速的事。 場景:A公司有100人,A公司只有一個公網IP,假設A公司可能有100個人同時在下載你的...
摘要:但是,你的連接數限制配置為允許單個連接數,單個連接數最大帶寬為。就降低單個連接數帶寬吧要知道大家誰沒事會用瀏覽器自帶下載器下載呢注本文只探討限速模塊在不同業務下的限速彩蛋偶爾發現,將連接數限制為迅雷不能高速下載了。 nginx 內置模塊限速怎么使用就不多說了,今天來說說連接數和單個連接數限速的事。 場景:A公司有100人,A公司只有一個公網IP,假設A公司可能有100個人同時在下載你的...
摘要:對于那些不想掛機還想使用高速下載的用戶來說,只要付費即可。元,元,元,滿足你的不同下載需求,如果你是周末偶爾看看電影,偶爾下載點學習資料,那么元的流量包最合適不過。 pandownload會被限速,這眾所周知,先看下我這個網盤的下載速度吧showImg(https://segmentfault.com/img/bVbvc7I); 下面我說說為啥我這個支持免登陸下載,而且不受到百度網盤的...
摘要:對于那些不想掛機還想使用高速下載的用戶來說,只要付費即可。元,元,元,滿足你的不同下載需求,如果你是周末偶爾看看電影,偶爾下載點學習資料,那么元的流量包最合適不過。 pandownload會被限速,這眾所周知,先看下我這個網盤的下載速度吧showImg(https://segmentfault.com/img/bVbvc7I); 下面我說說為啥我這個支持免登陸下載,而且不受到百度網盤的...
閱讀 1220·2021-11-25 09:43
閱讀 1976·2021-11-11 10:58
閱讀 1192·2021-11-08 13:18
閱讀 2686·2019-08-29 16:25
閱讀 3516·2019-08-29 12:51
閱讀 3312·2019-08-29 12:30
閱讀 753·2019-08-26 13:24
閱讀 3689·2019-08-26 10:38