Web开发的平民英雄:PHP+MySQL
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.2 文件上传模块

在PHP文件处理的功能上,还有一个重要的环节就是通过表单上传本地文件到Web服务器,如访客上传照片、管理员上传文件附件供访客下载等。

要想上传本地文件到服务器,必须使用表单POST方法,GET方法是不能实现此功能的,同时表单的enctype属性也必须设置为“multipart/form-data”。如下一个实现文件上传的表单。

        <form name="up" action="" enctype="multipart/form-data" method="post">
        <input name="file" type="file" size="60"/>
        <input name="ok" type="submit" value="上传" />
        </form>

文件上传到服务器之后,PHP提供了$_FILES全局变量数组来包含所有上传的文件信息。我们假设上传文件的<input>控件名称为“userfile”来说明$_FILES变量的元素:

$_FILES['userfile']['name']:客户端机器文件的原名称。

$_FILES['userfile']['type']:文件的MIME类型,如果浏览器提供此信息的话。一个例子是“image/gif”。不过MIME类型在PHP端并不检查,因此不要想当然认为有这个值。

$_FILES['userfile']['size']:已上传文件的大小,单位为字节。

$_FILES['userfile']['tmp_name']:文件被上传后在服务端储存的临时文件名。

$_FILES['userfile']['error']:和该文件上传相关的错误代码。此项目是在PHP 4.2.0版本中增加的。

文件被上传后,默认会被储存到服务端的临时目录中,除非php.ini中的upload_tmp_dir设置为其他的路径。服务端的默认临时目录可以通过更改PHP运行环境的环境变量TMPDIR来重新设置,但是在PHP脚本内部通过运行putenv() 函数来设置是不起作用的。该环境变量也可以用来确认其他的操作,也是在上传的文件上进行的。

接受上传文件的PHP脚本为了决定接下来要对该文件进行哪些操作,应该实现任何逻辑上必要的检查。例如可以用$_FILES['userfile']['size']变量来排除过大或过小的文件,也可以通过 $_FILES['userfile']['type']变量来排除文件类型和某种标准不相符合的文件,要么将该文件从临时目录中删除,要么将其移动到其他的地方。

PHP提供了is_uploaded_file()函数来检测某个文件是否为通过表单上传的临时文件,提供了move_uploaded_file()函数来将某个上传来的临时文件移动到其他指定目录中去。仍旧假设上传文件的<input>名为userfile:

        <?php
        $uploaddir = '/uploads/';
        $uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
        if           (is_uploaded_file($_FILES['userfile']['tmp_name'])           &&
        move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile))
        {
          echo "文件已经成功上传";
        }
        else
        {
          echo "上传文件处理出错!";
        }
        ?>

如果表单中没有选择上传的文件,则PHP变量$_FILES['userfile']['size']的值将为0,$_FILES['userfile']['tmp_name']将为空。

如果该文件没有被移动到其他地方也没有被改名,则该文件将在表单请求结束时被删除。

如果需要同时上传多个文件到服务器,我们可以书写多个文件上传控件来实现此功能,通过$_FILES[]数组来分别调用这些上传到服务器临时目录中的文件。

有一个窍门就是<input>控件的命名,可以类同checkbox多选框的命名,使用“[]”参与文件上传控件命名构造一个数组结构方便服务器调用。如:

        <form name="up" action="" enctype="multipart/form-data" method="post">
        <input name="file[]" type="file" size="60"/>
        <input name="file[]" type="file" size="60"/>
        <input name="file[]" type="file" size="60"/>
        <input name="ok" type="submit" value="上传" />
        </form>

假设用这个表单提交了多张照片到服务器。

        <?php
        foreach ($_FILES["file"]["error"] as $key => $error) {
          if ($error == UPLOAD_ERR_OK) {
              $tmp_name = $_FILES["file"]["tmp_name"][$key];
              $name = $_FILES["file"]["name"][$key];
              move_uploaded_file($tmp_name, "data/$name");
          }
        }
        ?>