PHP檔案上傳
要順利實(shí)現(xiàn)上傳功能,首先要在php.ini中開啟檔案上傳,並對(duì)其中一些參數(shù)做出合理的設(shè)置,找到 File Upload 項(xiàng) 可以看到下面有三個(gè)屬性,表示含義如下。
?file_upload :如果值為 on ,表示伺服器支援檔案上傳。否則反之
upload_tmp_dir : 上傳檔案暫存目錄。在檔案被成功上傳之前,檔案首先存放到伺服器的暫存目錄。如果想要知道位置,可以在後面設(shè)定存放路徑,否則,使用系統(tǒng)預(yù)設(shè)目錄
upload_max_filesize :伺服器允許上傳的檔案的最大值,以MB為單位。系統(tǒng)預(yù)設(shè)為2MB,使用者可自行設(shè)定
?★ 如果使用整合的安裝套件來(lái)設(shè)定PHP 的開發(fā)環(huán)境,上面介紹的這些設(shè)定資訊按預(yù)設(shè)已經(jīng)配置好了。
檔案上傳步驟
#為了更好的學(xué)習(xí)PHP,我們將複雜的PHP的檔案上傳歸納總結(jié)成為了6個(gè)步驟。
在實(shí)際使用過(guò)程中,依照這6個(gè)步驟就能夠很好的完成PHP的檔案上傳:
?一.判斷是否有錯(cuò)誤碼
系統(tǒng)傳回的錯(cuò)誤碼詳解:
? ? ?錯(cuò)誤碼 | ? ? 說(shuō)明 |
無(wú)錯(cuò)誤,可以繼續(xù)進(jìn)行檔案上傳的後續(xù)操作。 ############? ? ?1#########超出上傳檔案的最大限制,upload_max_filesize = 2M php.ini中設(shè)置,一般預(yù)設(shè)為2M。可依專案中的實(shí)際需求來(lái)修改###############? ? ?######? ? ?2### | 超出了指定的檔案大小,根據(jù)專案的業(yè)務(wù)需求指定上傳檔案的大小限制 |
#? ? ?3 | 只有部分檔案上傳 |
? ? ?4 | 檔案沒(méi)有上傳 |
? ? ?6 | #找不到暫存資料夾,可能目錄不存在或沒(méi)權(quán)限 |
? ? ?7 | 檔案寫入失敗,可能磁碟滿了或沒(méi)有權(quán)限 |
註★:錯(cuò)誤碼中沒(méi)有5
#二.自訂判斷是否超出檔案大小範(fàn)圍
在開發(fā)上傳功能時(shí)。我們作為開發(fā)人員,除了php.ini中規(guī)定的上傳的最大值外。
我們通常也會(huì)設(shè)定一個(gè)值,是業(yè)務(wù)規(guī)定的上傳大小限制。
例如:
新浪微博或QQ空間只準(zhǔn)單張頭像圖2M。而在上傳圖冊(cè)的時(shí)候又可以超過(guò)2M來(lái)上傳。
所以說(shuō),它的系統(tǒng)是支援更大檔案上傳的。
此處的判斷檔案大小,我們用來(lái)限制實(shí)際業(yè)務(wù)中我們想要規(guī)定的上傳的檔案大小。
。
#MIME(Multipurpose Internet Mail Extensions)是多用途網(wǎng)路郵件擴(kuò)充類型。是設(shè)定某種副檔名的檔案用一種應(yīng)用程式來(lái)開啟的方式類型,當(dāng)該副檔名檔案被存取的時(shí)
#候,瀏覽器會(huì)自動(dòng)使用指定應(yīng)用程式來(lái)開啟。多用於指定一些客戶端自訂的檔案名,以及一些媒體檔案開啟方式。?在判斷後綴和MIME類型的時(shí)候,我們會(huì)用到PHP的一個(gè)函數(shù)in_array(),該函數(shù)傳入兩個(gè)參數(shù)。
第一個(gè)參數(shù)是要判斷的值;第二個(gè)參數(shù)是範(fàn)圍數(shù)組。
因?yàn)椋行┤嗽谠杏忻舾嘘P(guān)鍵字會(huì)違反我國(guó)的相關(guān)法律和法規(guī)。
而移動(dòng)前不能瞎移動(dòng),或是移動(dòng)錯(cuò)了都是不科學(xué)的。移動(dòng)前我們需要使用相關(guān)函數(shù)判斷上傳的檔案是不是暫存檔案。
is_uploaded_file()傳入一個(gè)參數(shù)($_FILES中的快取檔案名稱),判斷傳入的名稱是不是上傳檔案。
六.移動(dòng)臨時(shí)文件到指定目錄
臨時(shí)檔案是真實(shí)的臨時(shí)文件,我們需要將其移動(dòng)到我們的網(wǎng)站目錄下面了。
讓我們網(wǎng)站目錄的數(shù)據(jù),其他人可以存取。
我們使用:move_uploaded_file()。
這個(gè)函數(shù)是將上傳檔案移到指定位置,並命名。
傳入兩個(gè)參數(shù):
第一個(gè)參數(shù)是指定移動(dòng)的上傳檔案;
第二個(gè)參數(shù)是指定的資料夾和名稱拼接的字串。
上傳檔案必須在網(wǎng)頁(yè)中準(zhǔn)備好一個(gè)form表單。就像下面這樣
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>PHP中文網(wǎng)</title> </head> <body> <form action="file.php" method="post" enctype="multipart/form-data"> <input type="file" name="file"> <input type="submit" value="上傳"> </form> </body> </html>
注意事項(xiàng):
1.??? form 表單中的參數(shù)method 必須為post。若為get是無(wú)法進(jìn)行檔案上傳的
2.??? enctype須為multipart/form-dat
3.??? 當(dāng)選擇??的 type=file 時(shí),預(yù)設(shè)為上傳檔案內(nèi)容。
上面的form表單提交的檔案內(nèi)容指向了file.php。
我們?cè)趂ile.php中,透過(guò)PHP程式碼,來(lái)處理上傳檔案。
我們選擇一個(gè)名為圖片進(jìn)行上傳。假設(shè)圖片的名稱為:.jpg,點(diǎn)選上傳。
PHP為檔案類別資料準(zhǔn)備了一個(gè)專用的系統(tǒng)函數(shù)$_FILES,上傳檔案的所有相關(guān)數(shù)據(jù),都保存在這個(gè)系統(tǒng)函數(shù)中。
在PHP檔案中,我們印出$_FILES ,來(lái)觀察這個(gè)陣列的結(jié)構(gòu):
<?php //var_dump()或print_r() //打印變量的相關(guān)信息,將變量的信息詳細(xì)的展示出來(lái) var_dump($_FILES); ?>
程式運(yùn)行結(jié)果:
array(1) {
? ["file"]=>
? array(5) {
??? ["name"]=>
??? string(7) "psu.jpg"
??? ["type"]=> ;
??? string(10) "image/jpeg"
??? ["tmp_name"]=>
??? string(22) "C:\Windows\phpE2F1.tmp"
?>
??? int(0)
??? ["size"]=>
??? int(488929)
? }
}
########################################################################################################################################################################################################C ###列印出來(lái)的結(jié)果的陣列結(jié)構(gòu)如下:#########
array (size=1)
??? 'file' =>
???????array (size=5)
??????'psu.jpg' (length=7)
??????//文件的mime類型
????? 'type' => string 'image/jpeg' (length=10)??
????? //快取文件,上傳的圖片即保存在這裡
????? 'tmp_name' => string 'E:\wamp\tmp\phpC32A.tmp' (length=23)
????? //錯(cuò)誤碼,詳見上面錯(cuò)誤碼介紹
????? 'error' => int 0??????????????????????????//上傳的檔案大小
????? 'size' =>int 225824????????
???#???
##很難很難得到了上面的陣列結(jié)構(gòu)。
我們就可以開始檔案的處理過(guò)程了
#<?php
header("Content-type:text/html;charset=utf-8");
if($_FILES['file']['error'] > 0){
switch ($_FILES['file']['error']) { //錯(cuò)誤碼不為0,即文件上傳過(guò)程中出現(xiàn)了錯(cuò)誤
case '1':
echo '文件過(guò)大';
break;
case '2':
echo '文件超出指定大小';
break;
case '3':
echo '只有部分文件被上傳';
break;
case '4':
echo '文件沒(méi)有被上傳';
break;
case '6':
echo '找不到指定文件夾';
break;
case '7':
echo '文件寫入失敗';
break;
default:
echo "上傳出錯(cuò)<br/>";
}
}else{
echo "上傳成功";//錯(cuò)誤碼為0,即上傳成功,可以進(jìn)行后續(xù)處理,處理流程見下文
}
?>
上面的程式碼詳細(xì)的介紹了錯(cuò)誤碼和對(duì)應(yīng)的錯(cuò)誤,我們可以根據(jù)錯(cuò)誤碼,來(lái)產(chǎn)生準(zhǔn)確的錯(cuò)誤提示。
第二步,判斷檔案是否超出大小。
?在實(shí)際專案中,由於系統(tǒng)硬體的限制,以及儲(chǔ)存裝置的限制,不可能讓使用者無(wú)限的上傳文件,所以我們要對(duì)用戶上傳的檔案大小進(jìn)行限制。定義一個(gè)適當(dāng)?shù)南拗拼笮?,能?/p>
我們的應(yīng)用更穩(wěn)定的運(yùn)作。 <?php
header("Content-type:text/html;charset=utf-8");
if($_FILES['file']['error'] > 0){
//有錯(cuò)誤可停止執(zhí)行
}else {
//當(dāng)前上傳文件無(wú)誤,運(yùn)行本段代碼
//判斷文件是否超出了指定的大小
//單位為byte
$MAX_FILE_SIZE = 100000
if ($_FILES['file']['size'] > $MAX_FILE_SIZE) {
//判斷,如果上傳的文件,大小超出了我們給的限制范圍,退上傳并產(chǎn)生錯(cuò)誤提示
exit("文件超出指定大小");
}
}
?>
將我們指定的檔案大小,定義為$MAX_FILE_SIZE,該變數(shù)的計(jì)數(shù)單位為byte,對(duì)應(yīng)上傳檔案的 $_FILES['file']['size']大小。
範(fàn)例程式碼中,限制大小約為100K及以下的檔案。
############第三步,判斷檔案的mime類型是否正確。 ############更多的時(shí)候,我們的文件上傳功能,都需要判斷用戶上傳的文件,是否符合要求,不可用的文件上傳以後,對(duì)於線上應(yīng)用的整體展示效果,會(huì)造成惡劣的影響。所以我們需通###過(guò)mime類型和後綴名,來(lái)判斷使用者上傳的檔案是否符合要求。
在下面的範(fàn)例程式碼中,我們假設(shè)當(dāng)前的專案需求為指定上傳圖片,要求上傳後綴名為GIF或jpg的文件,當(dāng)使用者上傳不符合要求的檔案時(shí),傳回錯(cuò)誤提示。
/*判斷後綴名和MIME類型是否符合指定需求
?
例如:
目前項(xiàng)目指定上傳後綴為.jpg或.gif的圖片,則$allowSuffix = array ('jpg','gif');
*/
?
?
//定義允許的後綴名數(shù)組
$myImg = explode('.', $_FILES['file' ]['name']);????????
?
/*
explode() 將一個(gè)字串用指定的字元切割,並傳回一個(gè)數(shù)組,這裡我們將檔案名稱用'.''切割,結(jié)果存在$myImg中,檔案的字尾名即為陣列的最後一個(gè)值
*/
?
?
$myImgSuffix = array_pop($myImg);
?
#/*
根據(jù)上傳檔案名稱取得檔案的後綴名
使用in_array()函數(shù),判斷上傳檔案是否符合要求
當(dāng)檔案後綴名不在我們?cè)试S的範(fàn)圍內(nèi)時(shí)退出上傳並傳回錯(cuò)誤訊息
*/
?
if(!in_array($myImgSuffix, $allowSuffix)){???????????????????? ?
?
/*
mime類型與文件後綴名的對(duì)應(yīng)關(guān)係,我們可以透過(guò)很多途徑查詢到,為了避免使用者自主修改檔案後綴名造成檔案無(wú)法使用。
mime類型也必須做出限制檢查mime類型,是為了防止上傳者直接修改檔案後綴名
導(dǎo)致檔案不可用或上傳的檔案不符合要求。
*/
?
//陣列內(nèi)容為允許上傳的mime類型
$allowMime = array(
??????????? "image/ "image/pjpeg",
??????????? "image/gif"
卷{????????????????????? //判斷上傳檔案的mime類型是否在允許的範(fàn)圍內(nèi)
????? exit?#}
第四步,產(chǎn)生指定的路徑和檔案名稱。
依照專案的檔案安排,產(chǎn)生檔案儲(chǔ)存路徑,為了避免檔案名稱重複而產(chǎn)生的錯(cuò)誤,依照一定的格式,產(chǎn)生一個(gè)隨機(jī)檔案名稱。
依照專案的檔案安排,產(chǎn)生檔案儲(chǔ)存路徑,為了避免檔案名稱重複而產(chǎn)生的錯(cuò)誤,依照一定的格式,產(chǎn)生一個(gè)隨機(jī)檔案名稱。
//指定上傳資料夾
$path = "upload/images/";
?
/*
根據(jù)目前時(shí)間產(chǎn)生隨機(jī)檔案名,本行程式碼是使用目前時(shí)間+ 隨機(jī)一個(gè)0-9的數(shù)字組合成檔名,後綴即為前面取到的檔案後綴名
*/
?
$name = date('Y').date( 'm').date("d").date('H').date('i').date('s').rand(0,9).'.'.$myImgSuffix;
第五步,判斷是否為上傳檔案。
is_uploaded_file()函數(shù)是專用的函數(shù),來(lái)判斷目標(biāo)檔案是否為上傳檔案。
<?php
?
//使用is_uploaded_file()判斷是否為上傳檔案,函數(shù)介紹見上文
if(is_uploaded_file($ _FILEs['file']['tmp_name'])){???
?
}
?>
/*
詳情請(qǐng)見範(fàn)例1
使用move_uploaded_file()移動(dòng)上傳文件至指定位置,第一個(gè)參數(shù)為上傳文件,第二個(gè)參數(shù)為我們?cè)谇懊嬷付ǖ纳蟼髀窂胶兔Q。
*/
?
if(move_uploaded_file($_FILEs['file']['tmp_name'], $path.$name)){
??????????? //提示檔案上傳成功#cho#choo#;上傳成功";???????????????????????????????
????????? echo '上傳失敗';????????????????????????????????}
??? }else {
??????? echo '不是上傳檔案';
??? }
?
}
?>
#我們將這個(gè)檔案片段整理成整個(gè)檔案:一個(gè)簡(jiǎn)單的上傳圖片的程式
多檔案上傳
介紹了PHP上傳單一檔案的過(guò)程。但有些時(shí)候,為了使用方便,我們需要滿足同時(shí)上傳多個(gè)檔案的需求。多文件上傳原理相同,不過(guò)在處理資料時(shí),需要對(duì)上傳資料進(jìn)行特殊處理。 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>PHP中文網(wǎng)</title>
</head>
<body>
<html>
<body>
<form action="morefile.php" method="post" enctype="multipart/form-data">
<input type="file" name="file[]">
<input type="file" name="file[]">
<input type="submit" value="上傳">
</form>
</body>
</html>
</body>
</html>
這裡有一個(gè)簡(jiǎn)易的上傳頁(yè)面,form表單同時(shí)提交了兩個(gè)檔案。我們 可以透過(guò)這個(gè)頁(yè)面提交內(nèi)容。
注意:
1.??? input type="file" name="file[]"與之前比較file後多加了一個(gè)中括號(hào)#2.??? 寫了2個(gè)或多個(gè)input type="file" name="file[]"?
陣列結(jié)構(gòu)如下array (size=1)?
????'file' =>?
????????array (size=5)
????'name' => #????????//檔案名稱
????????0 => string 'psu.jpg' (length=7)
?????##????'type' => array (size=2)
????????????0 => string 'image/jp?) (length=10)
c?10)
????//快取檔案
????'tmp_name' =>?
????????array (size=2)
????=23)
????????????1 => string 'E:\wamp\tmp\phpF6F5.tmp' (length=23)
????=2 )
????????????0 => int 0
????????????1 => ????array (size=2)
????????0 => ; int 225824????
????????1 => int 151651
#我們可以看到,兩個(gè)檔案儲(chǔ)存在一個(gè)陣列中,按鍵名稱和上傳單一檔案是相同。所以,需要我們用for()循環(huán),來(lái)分別取出兩個(gè)檔案的需要用到的資料。
在$_FILES中同時(shí)保存了兩個(gè)檔案的數(shù)據(jù),我們需要使用一個(gè)簡(jiǎn)單的循環(huán),來(lái)讀取單一檔案的信息,並將檔案移到我們想要放的位置。實(shí)例1for ($i=0; $i < count($_FILE['file']['name']); $i++) {?
?
/*
用is_uploaded_file ()函數(shù)判斷是上傳檔案
且沒(méi)有出錯(cuò)
*/
?
??? if(is_uploaded_file($_FILEs['file']['tmp_name'][$i]) && $_FILEs[ 'file']['error'][$i] == 0){????
???????if(move_uploaded_file($_FILEs['file']['tmp_name'][$i],'upload/'.$_FILE[ 'file']['name'][$i])){
??? //用move_uploaded_file()函數(shù)移動(dòng)檔案到指定的位置並使用檔案原名
????echo "上傳成功";
?
#??????? }else{
?
??????????? echo '在中失敗';
?
?????失敗';
?
}
?
}
詳細(xì)的判斷過(guò)程,請(qǐng)參考單一檔案上傳,這裡只做了基本的判斷,並沒(méi)有對(duì)檔案的大小及格式提醒。#已上傳圖片程式
##程式1 html 頁(yè)面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>PHP中文網(wǎng)</title> </head> <body> <form action="file-upload.php" enctype="multipart/form-data" method="post" name="uploadfile"> 上傳文件:<input type="file" name="upfile" /><br> <input type="submit" value="上傳" /></form> </form> </body> </html>程式2 ?提交到php 頁(yè)面<?php header("Content-type:text/html;charset=utf-8"); //print_r($_FILES["upfile"]); if(is_uploaded_file($_FILES['upfile']['tmp_name'])){ $upfile=$_FILES["upfile"]; //獲取數(shù)組里面的值 $name=$upfile["name"];//上傳文件的文件名 $type=$upfile["type"];//上傳文件的類型 $size=$upfile["size"];//上傳文件的大小 $tmp_name=$upfile["tmp_name"];//上傳文件的臨時(shí)存放路徑 //判斷是否為圖片 switch ($type){ case 'image/pjpeg':$okType=true; break; case 'image/jpeg':$okType=true; break; case 'image/gif':$okType=true; break; case 'image/png':$okType=true; break; } if($okType){ /** * 0:文件上傳成功<br/> * 1:超過(guò)了文件大小,在php.ini文件中設(shè)置<br/> * 2:超過(guò)了文件的大小MAX_FILE_SIZE選項(xiàng)指定的值<br/> * 3:文件只有部分被上傳<br/> * 4:沒(méi)有文件被上傳<br/> * 5:上傳文件大小為0 */ $error=$upfile["error"];//上傳后系統(tǒng)返回的值 echo "上傳文件名稱是:".$name."<br/>"; echo "上傳文件類型是:".$type."<br/>"; echo "上傳文件大小是:".$size."<br/>"; echo "上傳后系統(tǒng)返回的值是:".$error."<br/>"; echo "上傳文件的臨時(shí)存放路徑是:".$tmp_name."<br/>"; echo "開始移動(dòng)上傳文件<br/>"; //把上傳的臨時(shí)文件移動(dòng)到指定目錄下面 move_uploaded_file($tmp_name,'D:\upload/images/'.$name); $destination="D:\upload/images/".$name; echo "上傳信息:<br/>"; if($error==0){ echo "文件上傳成功啦!"; }elseif ($error==1){ echo "超過(guò)了文件大小,在php.ini文件中設(shè)置"; }elseif ($error==2){ echo "超過(guò)了文件的大小MAX_FILE_SIZE選項(xiàng)指定的值"; }elseif ($error==3){ echo "文件只有部分被上傳"; }elseif ($error==4){ echo "沒(méi)有文件被上傳"; }else{ echo "上傳文件大小為0"; } }else{ echo "請(qǐng)上傳jpg,gif,png等格式的圖片!"; } } ?>找一個(gè)圖片上傳,看看程式運(yùn)行結(jié)果實(shí)例2
#本例有4個(gè)檔案上傳域,文件網(wǎng)域的名字為u_file[] ,提交後上傳的檔案資料都被儲(chǔ)存到$_FILES[u_file]中,產(chǎn)生多維數(shù)組。讀取數(shù)組信息,並上傳文件。
程式1 html 頁(yè)面<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>PHP中文網(wǎng)</title> </head> <body> <html> <body> <p>請(qǐng)選擇要上傳的文件</p> <form action="morefile.php" method="post" enctype="multipart/form-data"> <table border="1" bgcolor="f0f0f0"> <tr> <td>上傳文件</td> <td><input type="file" name="u_file[]"></td> </tr> <tr> <td>上傳文件</td> <td><input type="file" name="u_file[]"></td> </tr> <tr> <td>上傳文件</td> <td><input type="file" name="u_file[]"></td> </tr> <tr> <td>上傳文件</td> <td><input type="file" name="u_file[]"></td> </tr> <tr> <td colspan="2"><input type="submit" value="上傳"></td> </tr> </table> </form> </body> </html> </body> </html>程式2 ?提交到php 頁(yè)面<?php header("Content-type:text/html;charset=utf-8"); if(!empty($_FILES[u_file][name])){ //判斷遍歷$_FILES是否為空 $file_name=$_FILES[u_file][name]; //將上傳文件名另存為數(shù)組 $file_tmp_name=$_FILES[u_file][tmp_name]; //將上傳的臨時(shí)文件名另存為數(shù)組 for($i=0;$i<count($file_name);$i++){ //循環(huán)上傳文件 if($file_name[$i]!=""){ //判斷上傳文件名是否為空 move_uploaded_file($file_tmp_name[$i],$i.$file_name[$i]); echo "文件" .$file_name[$i] ."上傳成功。更名為"."$file_name[$i]"."<br>"; } } } ?>執(zhí)行你的程式看看吧實(shí)例3
本範(fàn)例上傳表單,允許上傳大小為1MB 以下的檔案?
<from action="" method="POST" enctype="multipart/form-data"> <input type="file" name="file"> <input type="submit" value="上傳"> </from> <?php if(!empty($_FILES[file][name])){ //判斷是否有文件上傳 $fileinfo=$_FILES[file]; //將文件信息賦給變量$fileinfo if($fileinfo['size']<1000000 && $fileinfo['size']>0){ //判斷文件大小 echo "上傳成功"; }else{ echo "上傳文件太大或未知"; } } ?>執(zhí)行你的程式。###