對(duì)于任何一個(gè)網(wǎng)站肯定是少不了下載功能,常見(jiàn)的下載功能有圖片、視頻、Excel表格,如果文件比較小的話,那么不會(huì)遇到任何的問(wèn)題,但是當(dāng)文件信息而超過(guò)了PHP的最大內(nèi)存,那么在這個(gè)時(shí)候它就會(huì)有的內(nèi)存溢出的問(wèn)題。
成都創(chuàng)新互聯(lián)客戶idc服務(wù)中心,提供成都電信服務(wù)器托管、成都服務(wù)器、成都主機(jī)托管、成都雙線服務(wù)器等業(yè)務(wù)的一站式服務(wù)。通過(guò)各地的服務(wù)中心,我們向成都用戶提供優(yōu)質(zhì)廉價(jià)的產(chǎn)品以及開(kāi)放、透明、穩(wěn)定、高性價(jià)比的服務(wù),資深網(wǎng)絡(luò)工程師在機(jī)房提供7*24小時(shí)標(biāo)準(zhǔn)級(jí)技術(shù)保障。
那么它們是因?yàn)槭裁炊l(fā)生的?對(duì)于這個(gè)過(guò)程的原理才是我們應(yīng)該真正要去弄明白的事情
下載大數(shù)據(jù)量的EXCEL文件為何要報(bào)錯(cuò)?
PHP在下載大Excel表格的時(shí)候,那么首先它是需要去把MySQL的數(shù)據(jù)從硬盤上面讀取到內(nèi)存,但讀取它是一次性載入到我們的內(nèi)存,如果說(shuō)它一次性載入的數(shù)據(jù)量遠(yuǎn)遠(yuǎn)大于最大內(nèi)存,然后再來(lái)執(zhí)行瀏覽器的業(yè)務(wù)下載。那么這個(gè)時(shí)候它就會(huì)發(fā)生我們這個(gè)內(nèi)存溢出。
就比如:說(shuō)我們現(xiàn)在有100M的數(shù)據(jù)量,但是我們PHP內(nèi)存最大只有64M,那么這個(gè)它肯定是裝不了的,我們可以把那個(gè)內(nèi)存比喻為一個(gè)水杯,這個(gè)水杯的容量比喻為內(nèi)存,現(xiàn)在杯子最大容量為64L。你要存放100L??隙ǚ挪幌?/p>
大事化小,小事化了。拆分成段
從上面可以看到文件下載,它是分為兩步,首先是載入內(nèi)存然后執(zhí)行瀏覽器的輸出下載,那么既然大型文件一次性載入不了,那可以采用“大事化小,小事化了”思路,我們可以實(shí)現(xiàn)邊寫(xiě)邊下載,也就是分批次的讀取與寫(xiě)入。
因?yàn)橛脩舻脑挘灰罱K拿到這個(gè)文件就可以,對(duì)于瀏覽器的下載原理不需要關(guān)心。只需要給到文件下載提示給用戶即可,然后后端在實(shí)時(shí)的分批次的寫(xiě)入到要下載的文件當(dāng)中。
實(shí)現(xiàn)思路步驟:
1、一設(shè)置瀏覽器下載Excel需要的Header
2、打開(kāi)php://output流,并設(shè)置寫(xiě)入文件句柄。
注:(php://output,是一個(gè)可寫(xiě)的輸出流,允許程序像操作文件一樣將輸出寫(xiě)入到輸出流中,PHP會(huì)把輸出流中的內(nèi)容發(fā)送給web服務(wù)器并返回給發(fā)起請(qǐng)求的瀏覽器)
3、獲取數(shù)據(jù)庫(kù)所有數(shù)據(jù)量,并設(shè)置每次查詢的條數(shù),通過(guò)這兩個(gè)值計(jì)算分批查詢的次數(shù)
4、基于分批查詢的次數(shù)循環(huán)查詢數(shù)據(jù)庫(kù),然后寫(xiě)入到文件中,同時(shí)清除本次操作變量?jī)?nèi)存,刷新緩沖到瀏覽器,讓瀏覽器的文件始終實(shí)時(shí)保持到最新的大小
注:刷新用ob_flush、flush()
PHP的I/O流
在這里我們用到了PHP的一個(gè)IO的輸入輸出,也就是我們常用的
php://inputphp://output。
php://input
php://input可以讀取原始的POST數(shù)據(jù)。相較于$form-data”.
注:p
php://output是一個(gè)只寫(xiě)的數(shù)據(jù)流,允許你以print和echo一樣的方式寫(xiě)入到輸出緩沖區(qū)。
綜上:實(shí)現(xiàn)思維與原理很重要如有感悟,歡迎在線咨詢
你要的內(nèi)容太多了,只能簡(jiǎn)單的說(shuō)下。fopen (PHP 3, PHP 4, PHP 5)fopen -- 打開(kāi)文件或者 URL 說(shuō)明resource fopen ( string filename, string mode [, bool use_include_path [, resource zcontext]] )fopen() 將 filename 指定的名字資源綁定到一個(gè)流上。如果 filename 是 "scheme://..." 的格式,則被當(dāng)成一個(gè) URL,PHP 將搜索協(xié)議處理器(也被稱為封裝協(xié)議)來(lái)處理此模式。如果該協(xié)議尚未注冊(cè)封裝協(xié)議,PHP 將發(fā)出一條消息來(lái)幫助檢查腳本中潛在的問(wèn)題并將 filename 當(dāng)成一個(gè)普通的文件名繼續(xù)執(zhí)行下去。 如果 PHP 認(rèn)為 filename 指定的是一個(gè)本地文件,將嘗試在該文件上打開(kāi)一個(gè)流。該文件必須是 PHP 可以訪問(wèn)的,因此需要確認(rèn)文件訪問(wèn)權(quán)限允許該訪問(wèn)。如果激活了安全模式或者 open_basedir 則會(huì)應(yīng)用進(jìn)一步的限制。 如果 PHP 認(rèn)為 filename 指定的是一個(gè)已注冊(cè)的協(xié)議,而該協(xié)議被注冊(cè)為一個(gè)網(wǎng)絡(luò) URL,PHP 將檢查并確認(rèn) allow_url_fopen 已被激活。如果關(guān)閉了,PHP 將發(fā)出一個(gè)警告,而 fopen 的調(diào)用則失敗。 注意: 所支持的協(xié)議列表見(jiàn)附錄 N。某些協(xié)議(也被稱為 wrappers)支持 context 和/或 php.ini 選項(xiàng)。參見(jiàn)相應(yīng)的頁(yè)面哪些選項(xiàng)可以被設(shè)定(例如 php.ini 中用于 http wrapper 的 user_agent 值)。 注意: 對(duì) context 的支持是 PHP 5.0.0 添加的。有關(guān) context 的說(shuō)明見(jiàn)參考 CLX, Stream Functions。注意: 自 PHP 4.3.2 起,對(duì)所有區(qū)別二進(jìn)制和文本模式的平臺(tái)默認(rèn)模式都被設(shè)為二進(jìn)制模式。如果在升級(jí)后腳本碰到問(wèn)題,嘗試暫時(shí)使用 't' 標(biāo)記,直到所有的腳本都照以下所說(shuō)的改為更具移植性以后。 mode 參數(shù)指定了所要求到該流的訪問(wèn)類型??梢允且韵拢?表 1. fopen() 中 mode 的可能值列表mode說(shuō)明'r'只讀方式打開(kāi),將文件指針指向文件頭。 'r+'讀寫(xiě)方式打開(kāi),將文件指針指向文件頭。 'w'寫(xiě)入方式打開(kāi),將文件指針指向文件頭并將文件大小截為零。如果文件不存在則嘗試創(chuàng)建之。 'w+'讀寫(xiě)方式打開(kāi),將文件指針指向文件頭并將文件大小截為零。如果文件不存在則嘗試創(chuàng)建之。 'a'寫(xiě)入方式打開(kāi),將文件指針指向文件末尾。如果文件不存在則嘗試創(chuàng)建之。 'a+'讀寫(xiě)方式打開(kāi),將文件指針指向文件末尾。如果文件不存在則嘗試創(chuàng)建之。 'x'創(chuàng)建并以寫(xiě)入方式打開(kāi),將文件指針指向文件頭。如果文件已存在,則 fopen() 調(diào)用失敗并返回 FALSE,并生成一條 E_WARNING 級(jí)別的錯(cuò)誤信息。如果文件不存在則嘗試創(chuàng)建之。這和給 底層的 open(2) 系統(tǒng)調(diào)用指定 O_EXCL|O_CREAT 標(biāo)記是等價(jià)的。此選項(xiàng)被 PHP 4.3.2 以及以后的版本所支持,僅能用于本地文件。 'x+'創(chuàng)建并以讀寫(xiě)方式打開(kāi),將文件指針指向文件頭。如果文件已存在,則 fopen() 調(diào)用失敗并返回 FALSE,并生成一條 E_WARNING 級(jí)別的錯(cuò)誤信息。如果文件不存在則嘗試創(chuàng)建之。這和給 底層的 open(2) 系統(tǒng)調(diào)用指定 O_EXCL|O_CREAT 標(biāo)記是等價(jià)的。此選項(xiàng)被 PHP 4.3.2 以及以后的版本所支持,僅能用于本地文件。 注意: 不同的操作系統(tǒng)家族具有不同的行結(jié)束習(xí)慣。當(dāng)寫(xiě)入一個(gè)文本文件并想插入一個(gè)新行時(shí),需要使用符合操作系統(tǒng)的行結(jié)束符號(hào)?;?Unix 的系統(tǒng)使用 \n 作為行結(jié)束字符,基于 Windows 的系統(tǒng)使用 \r\n 作為行結(jié)束字符,基于 Macintosh 的系統(tǒng)使用 \r 作為行結(jié)束字符。 如果寫(xiě)入文件時(shí)使用了錯(cuò)誤的行結(jié)束符號(hào),則其它應(yīng)用程序打開(kāi)這些文件時(shí)可能會(huì)表現(xiàn)得很怪異。 Windows 下提供了一個(gè)文本轉(zhuǎn)換標(biāo)記('t')可以透明地將 \n 轉(zhuǎn)換為 \r\n。與此對(duì)應(yīng)還可以使用 'b' 來(lái)強(qiáng)制使用二進(jìn)制模式,這樣就不會(huì)轉(zhuǎn)換數(shù)據(jù)。要使用這些標(biāo)記,要么用 'b' 或者用 't' 作為
如果幫助到您,請(qǐng)記得采納為滿意答案哈,謝謝!祝您生活愉快! vae.la
php沒(méi)有這個(gè)概念的。
最常見(jiàn)的echo 還有var_dump一般打印數(shù)組用var_dump();
jsp中System.out.println()只要你使用這個(gè)打印方法,比如System.out.println(“aaa”);那么aaa就只在控制臺(tái)輸出,不在頁(yè)面輸出,不影響頁(yè)面效果。而PHP的echo等都會(huì)在頁(yè)面輸出。