PHP-文件上傳優化
- 2020 年 3 月 26 日
- 筆記
1.7 優化文件上傳
1.7.1 更改文件名
方法一:通過時間戳做文件名
<?php $path='face.stu.jpg'; //echo strrchr($path,'.'); //從最後一個點開始截取,一直截取到最後 echo time().rand(100,999).strrchr($path,'.');
方法二:通過uniqid()實現
$path='face.stu.jpg'; echo uniqid().strrchr($path,'.'),'<br>'; //生成唯一的ID echo uniqid('goods_').strrchr($path,'.'),'<br>'; //帶有前綴 echo uniqid('goods_',true).strrchr($path,'.'),'<br>'; //唯一ID+隨機數
1.7.2 驗證文件格式
方法一:判斷文件的擴展名(不能識別文件偽裝)
操作思路:將文件的後綴和允許的後綴對比
<body> <?php if(!empty($_POST)) { $allow=array('.jpg','.png','.gif'); //允許的擴展名 $ext=strrchr($_FILES['face']['name'],'.'); //上傳文件擴展名 if(in_array($ext,$allow)) echo '允許上傳'; else echo '文件不合法'; } ?> <form method="post" action="" enctype='multipart/form-data'> <input type="file" name="face"> <input type="submit" name="button" value="上傳"> </form> </body>
注意:比較擴展名不能防止文件偽裝。
方法二:通過$_FIELS[]['type']
類型(不能識別文件偽裝)
<body> <?php if(!empty($_POST)) { $allow=array('image/jpeg','image/png','image/gif'); //允許的類別 $mime=$_FILES['face']['type']; //上傳文件類型 if(in_array($mime,$allow)) echo '允許上傳'; else echo '文件不合法'; } ?> <form method="post" action="" enctype='multipart/form-data'> <input type="file" name="face"> <input type="submit" name="button" value="上傳"> </form> </body>
注意:比較$_FIELS[]['type']
不能防止文件偽裝。
方法三:php_fileinfo擴展(可以防止文件偽裝)
在php.ini中開啟fileinfo擴展
extension=php_fileinfo.dll
注意:開啟fileinfo擴展以後,就可以使用finfo_*的函數了

<body> <?php if(!empty($_POST)) { //第一步:創建finfo資源 $info=finfo_open(FILEINFO_MIME_TYPE); //var_dump($info); //resource(2) of type (file_info) //第二步:將finfo資源和文件做比較 $mime=finfo_file($info,$_FILES['face']['tmp_name']); //第三步,比較是否合法 $allow=array('image/jpeg','image/png','image/gif'); //允許的類別 echo in_array($mime,$allow)?'合法':'不合法'; } ?> <form method="post" action="" enctype='multipart/form-data'> <input type="file" name="face"> <input type="submit" name="button" value="上傳"> </form> </body>
小結:驗證文件格式有三種方法
1、可以驗證擴展名(不可以防止文件偽裝)
2、通過$_FILES[]['type']
驗證(不可以防止文件偽裝)
3、通過file_info擴展(可以防止文件偽裝)
1.7.3 優化文件上傳例題
步驟
第一步:驗證是否有誤
第二步:驗證格式
第三步:驗證大小
第四步:驗證是否是http上傳
第五步:上傳實現
<body> <?php /** *驗證錯誤 *如果有錯,就返回錯誤,如果沒錯,就返回null */ function check($file) { //1:驗證是否有誤 if($file['error']!=0){ switch($file['error']) { case 1: return '文件大小超過了php.ini中允許的最大值,最大值是:'.ini_get('upload_max_filesize'); case 2: return '文件大小超過了表單允許的最大值'; case 3: return '只有部分文件上傳'; case 4: return '沒有文件上傳'; case 6: return '找不到臨時文件'; case 7: return '文件寫入失敗'; default: return '未知錯誤'; } } //2、驗證格式 $info=finfo_open(FILEINFO_MIME_TYPE); $mime=finfo_file($info,$file['tmp_name']); $allow=array('image/jpeg','image/png','image/gif'); //允許的類別 if(!in_array($mime,$allow)){ return '只能上傳'.implode(',',$allow).'格式'; } //3、驗證大小 $size=123456789; if($file['size']>$size){ return '文件大小不能超過'.number_format($size/1024,1).'K'; } //4、驗證是否是http上傳 if(!is_uploaded_file($file['tmp_name'])) return '文件不是HTTP POST上傳的<br>'; return null; //沒有錯誤 } //表單提交 if(!empty($_POST)) { //上傳文件過程中有錯誤就顯示錯誤 if($error=check($_FILES['face'])){ echo $error; }else{ //文件上傳,上傳的文件保存到當天的文件夾中 $foldername=date('Y-m-d'); //文件夾名稱 $folderpath="./uploads/{$foldername}"; //文件夾路徑 if(!is_dir($folderpath)) mkdir($folderpath); $filename=uniqid('',true).strrchr($_FILES['face']['name'],'.'); //文件名 $filepath="$folderpath/$filename"; //文件路徑 if(move_uploaded_file($_FILES['face']['tmp_name'],$filepath)) echo "上傳成功,路徑是:{$foldername}/{$filename}"; else echo '上傳失敗<br>'; } } ?> <form method="post" action="" enctype='multipart/form-data'> <input type="file" name="face"> <input type="submit" name="button" value="上傳"> </form> </body>
運行結果

小結:
1、將時間戳轉換格式
echo date('Y-m-d H:i:s',1231346),'<br>'; //將時間戳轉成年-月-日 小時:分鐘:秒 echo date('Y-m-d H:i:s'),'<br>'; //將當前的時間轉成年-月-日 小時:分鐘:秒
2、設置時區(php.ini)

PRC:中華人民共和國
3、PHP的執行可以不需要Apache的參與
