PHP檔案上傳

要順利實現上傳功能,首先要在php.ini中開啟檔案上傳,並對其中一些參數做出合理的設置,找到 File Upload 項 可以看到下面有三個屬性,表示含義如下。

 file_upload :如果值為 on ,表示伺服器支援檔案上傳。否則反之

upload_tmp_dir : 上傳檔案暫存目錄。在檔案被成功上傳之前,檔案首先存放到伺服器的暫存目錄。如果想要知道位置,可以在後面設定存放路徑,否則,使用系統預設目錄

upload_max_filesize :伺服器允許上傳的檔案的最大值,以MB為單位。系統預設為2MB,使用者可自行設定

 ★ 如果使用整合的安裝套件來設定PHP 的開發環境,上面介紹的這些設定資訊按預設已經配置好了。


檔案上傳步驟

#為了更好的學習PHP,我們將複雜的PHP的檔案上傳歸納總結成為了6個步驟。

在實際使用過程中,依照這6個步驟就能夠很好的完成PHP的檔案上傳:

 一.判斷是否有錯誤碼

系統傳回的錯誤碼詳解:


#     0
     錯誤碼    說明


無錯誤,可以繼續進行檔案上傳的後續操作。

############     1#########超出上傳檔案的最大限制,upload_max_filesize = 2M php.ini中設置,一般預設為2M。可依專案中的實際需求來修改###############     ######     2###
超出了指定的檔案大小,根據專案的業務需求指定上傳檔案的大小限制
#     3只有部分檔案上傳
     4檔案沒有上傳
     6#找不到暫存資料夾,可能目錄不存在或沒權限
     7檔案寫入失敗,可能磁碟滿了或沒有權限
#

註★:錯誤碼中沒有5


#二.自訂判斷是否超出檔案大小範圍

在開發上傳功能時。我們作為開發人員,除了php.ini中規定的上傳的最大值外。

我們通常也會設定一個值,是業務規定的上傳大小限制。

例如:

新浪微博或QQ空間只準單張頭像圖2M。而在上傳圖冊的時候又可以超過2M來上傳。

所以說,它的系統是支援更大檔案上傳的。

此處的判斷檔案大小,我們用來限制實際業務中我們想要規定的上傳的檔案大小。





#MIME(Multipurpose Internet Mail Extensions)是多用途網路郵件擴充類型。是設定某種副檔名的檔案用一種應用程式來開啟的方式類型,當該副檔名檔案被存取的時

#候,瀏覽器會自動使用指定應用程式來開啟。多用於指定一些客戶端自訂的檔案名,以及一些媒體檔案開啟方式。

 在判斷後綴和MIME類型的時候,我們會用到PHP的一個函數in_array(),該函數傳入兩個參數。


第一個參數是要判斷的值;第二個參數是範圍數組。

我們用這個函數來判斷檔案的後綴名稱和mime型別是否在允許的範圍內。




#我們的檔案上傳成功了,不會讓它儲存原名。

因為,有些人在原名中有敏感關鍵字會違反我國的相關法律和法規。

我們可以採用date()、mt_rand()或unique()產生隨機的檔案名稱。

############.判斷是否是上傳檔案。 ###############我們的檔案上傳成功了,不會讓它儲存原名。 #########因為,有些人在原名中有敏感關鍵字會違反我國的相關法律和法規。 ############我們可以採用date()、mt_rand()或unique()產生隨機的檔案名稱。檔案上傳成功時,系統會將上傳的暫存檔案上傳到系統的暫存目錄中。產生一個臨時文件。 ######同時會產生暫存檔案名稱。我們需要做的事情是將臨時檔案移到系統的指定目錄中。 ###

而移動前不能瞎移動,或是移動錯了都是不科學的。移動前我們需要使用相關函數判斷上傳的檔案是不是暫存檔案。

is_uploaded_file()傳入一個參數($_FILES中的快取檔案名稱),判斷傳入的名稱是不是上傳檔案。


六.移動臨時文件到指定目錄

臨時檔案是真實的臨時文件,我們需要將其移動到我們的網站目錄下面了。

讓我們網站目錄的數據,其他人可以存取。

我們使用:move_uploaded_file()。
這個函數是將上傳檔案移到指定位置,並命名。
傳入兩個參數:
第一個參數是指定移動的上傳檔案;
第二個參數是指定的資料夾和名稱拼接的字串。

上傳檔案必須在網頁中準備好一個form表單。就像下面這樣

<!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>PHP中文网</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>

注意事項:

1.    form 表單中的參數method 必須為post。若為get是無法進行檔案上傳的

2.    enctype須為multipart/form-dat

3.    當選擇  的 type=file 時,預設為上傳檔案內容。

上面的form表單提交的檔案內容指向了file.php。

我們在file.php中,透過PHP程式碼,來處理上傳檔案。

我們選擇一個名為圖片進行上傳。假設圖片的名稱為:.jpg,點選上傳。

PHP為檔案類別資料準備了一個專用的系統函數$_FILES,上傳檔案的所有相關數據,都保存在這個系統函數中。

在PHP檔案中,我們印出$_FILES ,來觀察這個陣列的結構:

 <?php
//var_dump()或print_r()
//打印变量的相关信息,将变量的信息详细的展示出来
var_dump($_FILES);
?>

程式運行結果:

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 ###列印出來的結果的陣列結構如下:#########

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)
      //錯誤碼,詳見上面錯誤碼介紹
      'error' => int 0                          //上傳的檔案大小
      'size' =>int 225824        
   #   




##很難很難得到了上面的陣列結構。
我們就可以開始檔案的處理過程了


第一步,判斷錯誤碼

#

<?php
header("Content-type:text/html;charset=utf-8");
if($_FILES['file']['error'] > 0){
    switch ($_FILES['file']['error']) {    //错误码不为0,即文件上传过程中出现了错误
        case '1':
            echo '文件过大';
            break;
        case '2':
            echo '文件超出指定大小';
            break;
        case '3':
            echo '只有部分文件被上传';
            break;
        case '4':
            echo '文件没有被上传';
            break;
        case '6':
            echo '找不到指定文件夹';
            break;
        case '7':
            echo '文件写入失败';
            break;
        default:
            echo "上传出错<br/>";
    }
}else{
    echo "上传成功";//错误码为0,即上传成功,可以进行后续处理,处理流程见下文
}
?>

上面的程式碼詳細的介紹了錯誤碼和對應的錯誤,我們可以根據錯誤碼,來產生準確的錯誤提示。

 

第二步,判斷檔案是否超出大小。

 

在實際專案中,由於系統硬體的限制,以及儲存裝置的限制,不可能讓使用者無限的上傳文件,所以我們要對用戶上傳的檔案大小進行限制。定義一個適當的限制大小,能讓


我們的應用更穩定的運作。

<?php
header("Content-type:text/html;charset=utf-8");
if($_FILES['file']['error'] > 0){
    //有错误可停止执行
}else {
    //当前上传文件无误,运行本段代码
    //判断文件是否超出了指定的大小
    //单位为byte
    $MAX_FILE_SIZE = 100000
    if ($_FILES['file']['size'] > $MAX_FILE_SIZE) {
        //判断,如果上传的文件,大小超出了我们给的限制范围,退上传并产生错误提示
        exit("文件超出指定大小");
    }
}
?>
將我們指定的檔案大小,定義為$MAX_FILE_SIZE,該變數的計數單位為byte,對應上傳檔案的 $_FILES['file']['size']大小。

範例程式碼中,限制大小約為100K及以下的檔案。

############第三步,判斷檔案的mime類型是否正確。 ############更多的時候,我們的文件上傳功能,都需要判斷用戶上傳的文件,是否符合要求,不可用的文件上傳以後,對於線上應用的整體展示效果,會造成惡劣的影響。所以我們需通###

過mime類型和後綴名,來判斷使用者上傳的檔案是否符合要求。

在下面的範例程式碼中,我們假設當前的專案需求為指定上傳圖片,要求上傳後綴名為GIF或jpg的文件,當使用者上傳不符合要求的檔案時,傳回錯誤提示。

/*判斷後綴名和MIME類型是否符合指定需求
 
例如:
目前項目指定上傳後綴為.jpg或.gif的圖片,則$allowSuffix = array ('jpg','gif');
*/
 
 
//定義允許的後綴名數組
$myImg = explode('.', $_FILES['file' ]['name']);        
 
/*
explode() 將一個字串用指定的字元切割,並傳回一個數組,這裡我們將檔案名稱用'.''切割,結果存在$myImg中,檔案的字尾名即為陣列的最後一個值
*/
 
 
$myImgSuffix = array_pop($myImg);
 
#/*
根據上傳檔案名稱取得檔案的後綴名
使用in_array()函數,判斷上傳檔案是否符合要求
當檔案後綴名不在我們允許的範圍內時退出上傳並傳回錯誤訊息
*/
 
if(!in_array($myImgSuffix, $allowSuffix)){                      
 
/*
mime類型與文件後綴名的對應關係,我們可以透過很多途徑查詢到,為了避免使用者自主修改檔案後綴名造成檔案無法使用。
mime類型也必須做出限制檢查mime類型,是為了防止上傳者直接修改檔案後綴名
導致檔案不可用或上傳的檔案不符合要求。
*/
 
//陣列內容為允許上傳的mime類型
$allowMime = array(
            "image/ "image/pjpeg",
            "image/gif"
卷{                      //判斷上傳檔案的mime類型是否在允許的範圍內
      exit #}


第四步,產生指定的路徑和檔案名稱。

依照專案的檔案安排,產生檔案儲存路徑,為了避免檔案名稱重複而產生的錯誤,依照一定的格式,產生一個隨機檔案名稱。

依照專案的檔案安排,產生檔案儲存路徑,為了避免檔案名稱重複而產生的錯誤,依照一定的格式,產生一個隨機檔案名稱。

//指定上傳資料夾
$path = "upload/images/";
 
/*
根據目前時間產生隨機檔案名,本行程式碼是使用目前時間+ 隨機一個0-9的數字組合成檔名,後綴即為前面取到的檔案後綴名
*/
 
$name = date('Y').date( 'm').date("d").date('H').date('i').date('s').rand(0,9).'.'.$myImgSuffix;


第五步,判斷是否為上傳檔案。

is_uploaded_file()函數是專用的函數,來判斷目標檔案是否為上傳檔案。

<?php
 
//使用is_uploaded_file()判斷是否為上傳檔案,函數介紹見上文
if(is_uploaded_file($ _FILEs['file']['tmp_name'])){   
 
}
?>



################################### ####第六步,移動檔案到指定位置。 ###############使用move_uploaded_file()函數,將檔案移到指定的位置,並命名。要注意的是,Linux系統中對目標目錄是否有權限及磁碟空間是否足夠,否則會導致上傳操作失敗。 ###

/*
使用move_uploaded_file()移動上傳文件至指定位置,第一個參數為上傳文件,第二個參數為我們在前面指定的上傳路徑和名稱。
*/
 
if(move_uploaded_file($_FILEs['file']['tmp_name'], $path.$name)){
            //提示檔案上傳成功#cho#choo#;上傳成功";                               
          echo '上傳失敗';                                }
    }else {
        echo '不是上傳檔案';
    }
 
}
?>



#我們將這個檔案片段整理成整個檔案:一個簡單的上傳圖片的程式

詳情請見範例1

多檔案上傳


介紹了PHP上傳單一檔案的過程。但有些時候,為了使用方便,我們需要滿足同時上傳多個檔案的需求。多文件上傳原理相同,不過在處理資料時,需要對上傳資料進行特殊處理。

<!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>PHP中文网</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>
這裡有一個簡易的上傳頁面,form表單同時提交了兩個檔案。我們 可以透過這個頁面提交內容。

注意:

1.    input type="file" name="file[]"與之前比較file後多加了一個中括號

#2.    寫了2個或多個input type="file" name="file[]" 

陣列結構如下

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



#我們可以看到,兩個檔案儲存在一個陣列中,按鍵名稱和上傳單一檔案是相同。所以,需要我們用for()循環,來分別取出兩個檔案的需要用到的資料。

在$_FILES中同時保存了兩個檔案的數據,我們需要使用一個簡單的循環,來讀取單一檔案的信息,並將檔案移到我們想要放的位置。

for ($i=0; $i < count($_FILE['file']['name']); $i++) { 
 
/*
用is_uploaded_file ()函數判斷是上傳檔案
且沒有出錯
*/
 
    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()函數移動檔案到指定的位置並使用檔案原名
    echo "上傳成功";
 
#        }else{
 
            echo '在中失敗';
 
     失敗';
 
}
 
}



詳細的判斷過程,請參考單一檔案上傳,這裡只做了基本的判斷,並沒有對檔案的大小及格式提醒。

實例1

#已上傳圖片程式


##程式1 html 頁面

<!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>PHP中文网</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 頁面

<?php
 header("Content-type:text/html;charset=utf-8");
 //print_r($_FILES["upfile"]); 
 if(is_uploaded_file($_FILES['upfile']['tmp_name'])){
     $upfile=$_FILES["upfile"];
 //获取数组里面的值 
     $name=$upfile["name"];//上传文件的文件名
     $type=$upfile["type"];//上传文件的类型
     $size=$upfile["size"];//上传文件的大小
     $tmp_name=$upfile["tmp_name"];//上传文件的临时存放路径
 //判断是否为图片 
     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:超过了文件大小,在php.ini文件中设置<br/>
          * 2:超过了文件的大小MAX_FILE_SIZE选项指定的值<br/>
          * 3:文件只有部分被上传<br/>
          * 4:没有文件被上传<br/>
          * 5:上传文件大小为0
          */
         $error=$upfile["error"];//上传后系统返回的值
         echo "上传文件名称是:".$name."<br/>";
         echo "上传文件类型是:".$type."<br/>";
         echo "上传文件大小是:".$size."<br/>";
         echo "上传后系统返回的值是:".$error."<br/>";
         echo "上传文件的临时存放路径是:".$tmp_name."<br/>";
 
         echo "开始移动上传文件<br/>";
 //把上传的临时文件移动到指定目录下面
         move_uploaded_file($tmp_name,'D:\upload/images/'.$name);
         $destination="D:\upload/images/".$name;
 
         echo "上传信息:<br/>";
         if($error==0){
             echo "文件上传成功啦!";
 
         }elseif ($error==1){
             echo "超过了文件大小,在php.ini文件中设置";
         }elseif ($error==2){
             echo "超过了文件的大小MAX_FILE_SIZE选项指定的值";
         }elseif ($error==3){
             echo "文件只有部分被上传";
         }elseif ($error==4){
             echo "没有文件被上传";
         }else{
             echo "上传文件大小为0";
         }
     }else{
         echo "请上传jpg,gif,png等格式的图片!";
     }
 }
 ?>

找一個圖片上傳,看看程式運行結果

實例2

#本例有4個檔案上傳域,文件網域的名字為u_file[] ,提交後上傳的檔案資料都被儲存到$_FILES[u_file]中,產生多維數組。讀取數組信息,並上傳文件。

程式1 html 頁面

<!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>PHP中文网</title>
 </head>
 <body>
 <html>
 <body>
 <p>请选择要上传的文件</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 頁面

<?php
header("Content-type:text/html;charset=utf-8");
if(!empty($_FILES[u_file][name])){           //判断遍历$_FILES是否为空
    $file_name=$_FILES[u_file][name];         //将上传文件名另存为数组
    $file_tmp_name=$_FILES[u_file][tmp_name];      //将上传的临时文件名另存为数组
    for($i=0;$i<count($file_name);$i++){         //循环上传文件
        if($file_name[$i]!=""){                 //判断上传文件名是否为空
            move_uploaded_file($file_tmp_name[$i],$i.$file_name[$i]);
            echo "文件" .$file_name[$i] ."上传成功。更名为"."$file_name[$i]"."<br>";
        }
    }
}
?>

執行你的程式看看吧

實例3

本範例上傳表單,允許上傳大小為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 "上传文件太大或未知";
    }
}
?>

執行你的程式。


###
繼續學習
||
<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 "上传文件太大或未知"; } } ?>