使用Zend框架實(shí)現(xiàn)PHP文件上傳
Zend Framework是流行的PHP開(kāi)發(fā)框架,使用Zend框架,能夠方便快捷的實(shí)現(xiàn)各項(xiàng)常用功能。這里向你介紹使用Zend框架來(lái)創(chuàng)建文件上傳功能,該機(jī)制能夠輕而易舉地接收、確認(rèn)和處理要上傳的文件。
一、簡(jiǎn)介
無(wú)論是管理YouTube上的視頻、在SlideShare上共享PowerPoint演示文稿,還是使用開(kāi)源電子商務(wù)平臺(tái)Magento更新在線商店中的商品圖像,我們都有用到基于web的文件上傳功能。但是,這個(gè)功能到底是如何工作的呢?文件是如何從本地機(jī)器傳送到遠(yuǎn)程服務(wù)器的?本文將向讀者詳細(xì)介紹如何使用流行的Zend框架來(lái)創(chuàng)建我們自己的PHP文件上傳機(jī)制,該機(jī)制能夠輕而易舉地接收、確認(rèn)和處理要上傳的文件。
二、配置處理文件上載的PHP
PHP本身能夠通過(guò)Web表單來(lái)完成文件上載,不過(guò)無(wú)論使用標(biāo)準(zhǔn)PHP代碼還是使用Zend框架來(lái)管理文件上傳,都有必要花一些時(shí)間來(lái)檢測(cè)直接影響PHP的有關(guān)功能的配置偽指令,這些指令包括:
◆file_uploads:這個(gè)偽指令啟用PHP的文件上載功能。在默認(rèn)情形下,這個(gè)偽指令會(huì)被啟用。
◆upload_max_filesize:這個(gè)偽指令定義了要上載的文件的最大尺寸。在默認(rèn)情形下,這個(gè)偽指令被設(shè)置為2M。
◆upload_tmp_dir:這個(gè)偽指令定義了PHP臨時(shí)存儲(chǔ)要上傳的文件的目錄,文件在傳入最終目的地之前將臨時(shí)存放于此,該目錄是由開(kāi)發(fā)人員指定的。在默認(rèn)情形下,這個(gè)偽指令不會(huì)賦值,這意味著PHP將使用系統(tǒng)的默認(rèn)值,舉例來(lái)說(shuō),許多l(xiāng)inux發(fā)行版中的臨時(shí)目錄為/tmp。
◆post_max_size:設(shè)定POST 數(shù)據(jù)所允許的最大大小。php默認(rèn)的post_max_size 為2M。
◆max_execution_time:雖然與文件上載的關(guān)系不是非常密切,但是這個(gè)偽指令在PHP的文件上載功能中卻扮演了一個(gè)重要角色,因?yàn)樗x了PHP腳本的執(zhí)行時(shí)間。對(duì)于尺寸特別大的文件來(lái)說(shuō),可能需要很長(zhǎng)的時(shí)間才能傳輸?shù)轿募?wù)器,所以可以考慮將這個(gè)偽指令的默認(rèn)值即30秒改為60乃至90秒。
三、創(chuàng)建文件上載表單
下面我們將創(chuàng)建一個(gè)Web表單示例,它能夠用來(lái)瀏覽本地計(jì)算機(jī)的文件系統(tǒng)以及確定要上傳的文件。我們將盡力使該示例保持簡(jiǎn)單,創(chuàng)建的文件上載表單的外觀如圖1所示。
這個(gè)表單的創(chuàng)建方式跟我們之前創(chuàng)建的其他表單大同小異,只是有一些輕微的區(qū)別。用于創(chuàng)建這個(gè)表單的HTML代碼如清單1所示。按照Z(yǔ)end框架的慣例,我們將這個(gè)表單放入名為upload.phtml的視圖中,它是名為admin的控制器中動(dòng)作upload的一部分。
- <form enctype="multipart/form-data" method="post" action="/admin/upload">
- <p>
- What file would you like to upload?<br />
- <input type="file" name="video-upload" size="40" />
- < SPAN>p>
- <p>
- <input type="submit" name="submit" class="submit" value="Upload Video" />
- < SPAN>p>
- < SPAN>form>
在這個(gè)表單中,有兩處代碼需要格外注意:
enctype="multipart/form-data":當(dāng)我們使用Web表單發(fā)送大量的二進(jìn)制數(shù)據(jù)的時(shí)候,就應(yīng)該使用這個(gè)表單屬性。因?yàn)橹T如電子表格以及視頻等文件中含有大量的二進(jìn)制數(shù)據(jù),所以創(chuàng)建文件上載表單時(shí)應(yīng)該包含這個(gè)屬性。
- <input type="file" name="video-upload" size="40" />
#T#上面這個(gè)表單元素會(huì)創(chuàng)建允許用戶在本地文件系統(tǒng)搜索要上傳的文件的表單機(jī)制。當(dāng)提交按鈕被按下的時(shí)候,這個(gè)文件將被上傳,并將其發(fā)送給表單動(dòng)作所標(biāo)識(shí)的腳本(本例中,為upload.php)做進(jìn)一步的處理。
如上所述,文件將被上傳給表單的動(dòng)作屬性所標(biāo)識(shí)的腳本。然而,除非該腳本對(duì)該文件做實(shí)際的處理,否則數(shù)據(jù)會(huì)被丟失。在下一節(jié)中,我們將介紹如何使用Zend框架的Zend_File_Transfer組件來(lái)處理上傳的文件。#p#
四、關(guān)于Zend_File_Transfer組件
如同Zend框架的其他強(qiáng)大組件旨在簡(jiǎn)化我們的開(kāi)發(fā)任務(wù)那樣,Zend_File_Transfer組件旨在簡(jiǎn)化從用戶的計(jì)算機(jī)向web服務(wù)器上傳文件的工作。實(shí)際上,這個(gè)組件在處理文件上傳方面非常靈活,它可以使用諸如FTP和WebDAV協(xié)議來(lái)傳送文件,不過(guò)我們這里只討論它的最初設(shè)計(jì)意圖。讓我們首先創(chuàng)建最簡(jiǎn)單上載動(dòng)作處理,不過(guò)它仍能接收和處理一個(gè)上載的文件,如下所示:
- public function uploadAction()
- {
- if ($this->getRequest()->isPost()) {
- $upload = new Zend_File_Transfer_Adapter_Http();
- $upload->setDestination($this->config->uploads->product->supplements);
- if ($upload->receive()) {
- echo "The file has been uploaded!";
- }
- }
- }
為了在下面的描述中輕松引用代碼,我們這里為動(dòng)作代碼添加了相應(yīng)的行號(hào)。
04行的代碼確定POST請(qǐng)求是否已經(jīng)提交給了該動(dòng)作。這對(duì)于創(chuàng)建為用戶呈現(xiàn)表單以及通過(guò)表單提交數(shù)據(jù)的動(dòng)作來(lái)說(shuō)都非常有用。
06行的代碼調(diào)用Zend_File_Transfer類組件,并使用了能夠處理通過(guò)Web表單提交的數(shù)據(jù)的HTTP適配器。
08行的代碼用于設(shè)置文件上傳的最終目的地。雖然可以直接向該方法傳遞一個(gè)路徑,不過(guò)我發(fā)現(xiàn)將路徑存放到application.ini文件中然后根據(jù)需要檢索配置參數(shù)會(huì)更加方便一些。 這允許我們依照要求輕松更改目的地路徑,當(dāng)我們的代碼從開(kāi)發(fā)工作站遷移到生產(chǎn)服務(wù)器時(shí)這一點(diǎn)格外有用。
10行的代碼負(fù)責(zé)接收文件,并將其移動(dòng)到要求的目的地。
或許您覺(jué)得這難以置信,但是這短短的十六行代碼的確能夠接收并將上傳來(lái)的文件移動(dòng)到服務(wù)器的預(yù)定位置! 然而,現(xiàn)在還不要高興得太早,因?yàn)樵撃_本缺少接收用戶輸入時(shí)應(yīng)具備的一個(gè)關(guān)鍵步驟,因?yàn)檫@個(gè)腳本允許用戶上傳任意文件,這是萬(wàn)萬(wàn)不可的! 幸運(yùn)的是,Zend_File_Transfer組件帶有檢查文件上傳處理方面能夠想到的所有方面的數(shù)據(jù)驗(yàn)證方法。
五、對(duì)上載的文件進(jìn)行檢驗(yàn)
我們至少希望檢查被上傳文件的一個(gè)或者幾個(gè)關(guān)鍵特性,如文件的大小,或者M(jìn)IME類型等。實(shí)際上,有多種方法可以用來(lái)檢索這些特性。舉例來(lái)說(shuō),為了檢索文件的MIME類型,我們可在接收文件之后調(diào)用getMimeType()方法,具體代碼如下所示:
- if ($upload->receive()) {
- echo "The file type is {$upload->getMimeType()}";
- }
如果我們向服務(wù)器上傳了一個(gè)PDF文件,并調(diào)用了getMimeType方法,那么將會(huì)返回application/x-pdf。當(dāng)用戶只應(yīng)上傳特定類型的文件時(shí),這個(gè)方法非常有用。下面是一個(gè)例子:
- if ($upload->getMimeType() == "application/x-pdf") {
- $upload->receive();
- echo "File received";
- } else {
- echo "Please upload a PDF";
- }
當(dāng)然,檢查文件大小或者類型只是證實(shí)過(guò)程的一小部分而已。為了簡(jiǎn)化驗(yàn)證工作,您可能希望在接收被上傳的文件之前來(lái)進(jìn)行這些工作,實(shí)際上Zend_File_Transfer組件已經(jīng)為我們提供了18個(gè)驗(yàn)證方法。Zend框架文檔提供了這些驗(yàn)證函數(shù)的完整說(shuō)明。我們可能用到的驗(yàn)證函數(shù)之一便是ImageSize,它能檢查一個(gè)被上載圖像的大小,以便確保其大小介于給定的最大和最小尺寸之間。在某些情況下,這可能非常有用,例如在需要保持縮略圖尺寸保持一致的時(shí)候。下面的例子將確保所有上傳的圖像都為PNG類型,同時(shí)其大小符合160×160像素的要求:
- if ($this->getRequest()->isPost()) {
- $upload = new Zend_File_Transfer_Adapter_Http();
- $upload->setDestination($this->config->uploads->product->supplements);
- $upload->addValidator('MimeType', false, 'image/png');
- $upload->addValidator('ImageSize', false,
- array('minwidth' => 160,
- 'maxwidth' => 160,
- 'minheight' => 160,
- 'maxheight' => 160)
- );
- if ($upload->isValid()) {
- $upload->receive();
- echo "File received";
- } else {
- echo "Please upload a file of type PNG and dimensions 160x160 pixels.";
- }
- }
六、進(jìn)一步閱讀
如今,用戶驅(qū)動(dòng)的內(nèi)容已經(jīng)成為Web的關(guān)鍵組成部分,所以項(xiàng)目的成功可能會(huì)取決于數(shù)據(jù)從用戶到web服務(wù)器的傳送效率。在為用戶提供數(shù)據(jù)上傳功能的時(shí)候,Zend框架的Zend_File_Transfer組件可以極大的降低開(kāi)發(fā)工作的復(fù)雜性!
如果您想進(jìn)一步了解Zend_File_Transfer組件,請(qǐng)參考Zend框架的Zend_File組件文檔;另外,PHP手冊(cè)的文檔也有文件上載方面的介紹;此外,Zend_ProgressBar組件的進(jìn)一步信息請(qǐng)參考Zend框架的Zend_ProgressBar文檔。