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类型是否符合

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"
    ["error"]=>
    int(0)
    ["size"]=>
    int(488929)
  }
}

打印出来的结果的数组结构如下:

array (size=1)
    'file' =>
       array (size=5)
       //文件名
      'name' => string '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)){                            
        exit("文件后缀名不符");
}
 
/*
mime类型和文件后缀名的对应关系,我们可以通过很多途径查询到,为了避免用户自主修改文件后缀名造成文件无法使用。
mime类型也必须做出限制检查mime类型,是为了防止上传者直接修改文件后缀名
导致文件不可用或上传的文件不符合要求。
*/
 
//数组内容为允许上传的mime类型
$allowMime = array(
            "image/jpg",
            "image/jpeg",
            "image/pjpeg",
            "image/gif"
            );
 
 
if(!in_array($_FILES['file']['type'], $allowMime)){                      //判断上传文件的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)){
            //提示文件上传成功
            echo "上传成功";                               
        }else{
/*
文件移动失败,检查磁盘是否有足够的空间, */
            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' => 
        array (size=2)
        //文件名
        0 => string 'psu.jpg' (length=7)
        1 => string 'qwe.jpg' (length=7)
    //文件mime类型
    'type' => array (size=2)
            0 => string 'image/jpeg' (length=10)
            1 => string 'image/jpeg' (length=10)
    //缓存文件
    'tmp_name' => 
        array (size=2)
            0 => string 'E:\wamp\tmp\phpF6D5.tmp' (length=23)
            1 => string 'E:\wamp\tmp\phpF6F5.tmp' (length=23)
    //文件错误信息
    'error' => 
        array (size=2)
            0 => int 0
            1 => int 0
    //文件大小
    'size' => 
        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 '上传失败';
 
        }
 
    }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 "上传文件太大或未知"; } } ?>
提交重置代码
章节
笔记
提问
课件
反馈
捐赠

PHP 零基础入门教程