用菜鳥的眼光淺談php上傳檔案
來源:互聯網
上載者:User
本人由於想寫個discuz外掛程式,這個外掛程式功能上涉及到上傳檔案這一功能,故以菜鳥的眼光來學習了下php上傳檔案。 首先,w3cshool查了下案例,覺得他說的非常詳細,連我這個菜鳥都略懂了一二。 貼上地址:http://www.w3school.com.cn/php/php_file_upload.asp 照著這個講解,寫了下他這個demo,貼上代碼: html: <form action="demo.php" method="post" enctype="multipart/form-data"> <label for="file">Filename:</label> <input type="file" name="file" id="file"> <br/> <input type="submit" name="submit" value="Submit"/></form>這個表單頁,作為php菜鳥的我說下我在這個裡面學到的新東西: 1.form的屬性enctype,百度翻譯了下這個單詞,才知道,這個是encode type 的縮寫,就是指定往伺服器傳遞資訊的編碼格式; 2.input的type屬性file,這個專用檔案上傳的; php: 複製代碼//echo phpinfo();//var_dump($_FILES);die; if((($_FILES["file"]["type"]=="image/gif")($_FILES["file"]["type"]=="image/jpeg")($_FILES["file"]["type"]=="image/pjpeg")) && ($_FILES["file"]["size"]<100*1024*1024)){ if($_FILES["file"]["error"]>0){ echo "Error: ".$_FILES["file"]["error"]."<br/>"; }else{ echo "Upload: ".$_FILES["file"]["name"]."<br/>"; echo "Type: ".$_FILES["file"]["type"]."<br />"; echo "Size: ".($_FILES["file"]["size"]/1024)."Kb<br />"; echo "Stored in ".$_FILES["file"]["tmp_name"]; } if(file_exists("upload/".$_FILES["name"]["name"])){ echo $_FILES["file"]["name"]."already exists."; }else{ move_uploaded_file($_FILES["file"]["tmp_name"],"upload/".$_FILES["file"]["name"]); echo "Stored in: "."upload/".$_FILES["file"]["name"]; }}else{ echo "Invalid file";}複製代碼關於調試這個demo的時候,我遇到一個問題:就是運行這個demo的時候php報出warning,表示上傳不成功。 這個時候我就想列印出$_FILES這個變數來看看,結果列印出來發現error=1;才知道上傳的檔案超過了php.ini的上傳檔案大小,導致上傳失敗。 這裡說下俺新瞭解的知識點: 複製代碼 PHP程式設計語言中的常見的$_FILES 系統函數用法有: $_FILES['myFile']['name'] 顯示用戶端檔案的原名稱。 $_FILES['myFile']['type'] 檔案的 MIME 類型,例如"image/gif"。 $_FILES['myFile']['size'] 已上傳檔案的大小,單位為位元組。 $_FILES['myFile']['tmp_name'] 儲存的臨時檔案名稱,一般是系統預設。 $_FILES['myFile']['error'] 該檔案上傳相關的錯誤碼。以下為不同代碼代表的意思: 0; 檔案上傳成功。 1; 超過了檔案大小php.ini中即系統設定的大小。 2; 超過了檔案大小 MAX_FILE_SIZE 選項指定的值。 3; 檔案只有部分被上傳。 4; 沒有檔案被上傳。 5; 上傳檔案大小為0。複製代碼 到這裡,應該就知道了我剛剛運行demo的錯誤是啥導致的,那既然發現是php.ini裡面限制超出了,那接下來我就修改了下php.ini的配置。 總結下我修改這個php.ini上傳限制的感受:首先,要修改php上傳檔案大小限制,那要改php.ini裡面的兩個參數,一個是upload_max_filesize,還有個就是post_max_size,修改下這兩個參數的大小就可以了!其次,就是找准php.ini的位置,我由於本地電腦搭建的是Integration Environment,所以php.ini在apache檔案夾下面,如果是自己搭建的環境,那就在php檔案夾下面,如果找不到,echo下phpinfo(),可以看到php.ini檔案的位置。 那到此為止,跟我差不多的新手們就能運行w3cshool上面的demo了,完成上傳執行個體了。 關於上傳檔案,我看了下discuz其他外掛程式作者開發的外掛程式,有點小收穫,貼上來跟大家分享下:複製代碼 $fileTypes = array('mp3','wav'); //定義允許上傳的檔案類型 $result = null; $uploadDir = './mail'; //上傳路徑 if(!submitcheck($_POST['formhash2'])){ //檢測是否是上傳檔案 if($_POST['upname']==''){ //判斷上傳檔案的命名是否為空白 $result=lang('plugin/saya_mails', 'noname'); }else{ $myfile = $_FILES['myfile']; //擷取上傳的檔案資訊 $myfileType = substr($myfile['name'], strrpos($myfile['name'], ".") + 1); //兩種擷取上傳檔案的尾碼名 // $myfileTyle = substr(strrchr($myfile['name'],'.'),1); if ($myfile['size'] > 1024*1024*1024) { //判斷上傳檔案大小是否超過限制 $result = lang('plugin/saya_mails', 'big'); } else if (!in_array($myfileType, $fileTypes)) { //判斷是否是允許上傳的類型 $result = lang('plugin/saya_mails', 'type'); } elseif (is_uploaded_file($myfile['tmp_name'])) { //判斷是否是通過HTTP post上傳的檔案 $toFile = './source/plugin/saya_mails/mail/' . $myfile['name']; //目標儲存地址 if (@move_uploaded_file($myfile['tmp_name'], $toFile)) { //將檔案拷貝到目標儲存地址 //這個地方加@是屏蔽錯誤資訊和警告// if (copy($myfile['tmp_name'],$toFile)) { $end=0; $result = lang('plugin/saya_mails', 'success'); } else { $result = lang('plugin/saya_mails', 'unknow'); } } else { $result = lang('plugin/saya_mails', 'big'); } } }複製代碼 對比了下,w3cshool上面的上傳執行個體,覺得這個作者寫的更完善一點 大體流程就是: 1.判斷是否是上傳檔案,他用的這個方法是discuz內建的,我們一般用,就是form傳遞過來的隱藏參數的值存不存在來進行判斷; 2.判斷上傳檔案的命名是否為空白,這一步大家可以跳過,這個是他自己寫了個input而已; 3.判斷上傳大小是否超出; 4.擷取檔案尾碼名,判斷是否是允許的上傳檔案類型; 5.判斷檔案是否是通過http post上傳的; 6.移動儲存檔案; 關於以上流程,個人總結了下自己獲得的新的知識點: 1.關於擷取檔案的尾碼名,原外掛程式作者是通過函數strrpos()來返回"."所在的位置,然後通過截取函數substr()來獲得上傳檔案的尾碼。 這裡,strrpos()函數,我自己的理解應該是string return position的縮寫,當然我還沒查證過!這個函數是返回字串裡要尋找的字串最後出現的位置,並返回這個位置。也就是從後往前查,第一次出現的位置。參考地址:http://www.w3school.com.cn/php/func_string_strrpos.asp 這裡原作者用這個方法來判斷,肯定是可以的,我百度了下,發現也可以用strrchr()和substr()函數合作來實現這個方法,我把我想的方法注釋在了上面原始碼裡面了,其實差不多,strrchr()函數就是返回最後一次出現的要尋找的字串到結尾的字串,參考地址:http://www.w3school.com.cn/php/func_string_strrchr.asp 通過以上兩種方法來判斷上傳檔案的類型是否達標,而不是通過$_FILES["file"]["type"]來判斷,這樣更好判斷點,對於新手,因為只要你列印下$_FILES這個參數你就知道了,type屬性沒這麼判斷來的清晰明了。 2.通過is_uploaded_file()來判斷檔案是否是通過http上傳的 3.move_uploaded_file()前面的@是用來屏蔽錯誤資訊和警告的