本人由於想寫個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的位置,我由於本地電腦搭建的是集成環境,所以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()前面的@是用來屏蔽錯誤信息和警告的