5.4 文件上传
PHP除了可以接收表单中提交的数据外,还可以接收客户端上传的文件数据。本节介绍PHP中文件上传的方法。
5.4.1 使用POST方法上传文件
在HTML文档中,可以使用表单来提交要上传的文件。下面是一个上传文件表单的定义代码:
<form name="form1" method="post" action="upfile.php" enctype="multipart/form-data">
……
<input type="file" name="file1" style="width:80%" value="">
<input type="submit" name="Submit" value="上传">
</form>
其中省略了一些说明文字和用于对齐的表格。可以看到,在定义表单中使用了enctype="multipart/form-data",这是使用表单上传文件的固定编码格式。action="upfile.php"表示upfile.php是处理上传文件的脚本。表单中使用一个文本框(input)控件来要求用户选择上传的文件,控件的类型为“file”,控件名为file1。上面定义的上传文件网页upload.html如图5-16所示。
图5-16 上传文件的网页upload.html
在处理脚本upfile.php中,可以使用全局变量$_FILES来获取上传文件的信息。$FILES是一个数组,它可以保存所有上传文件的信息。如果上传文件的文本框名称为 file1,则可以使用$FILES[file1]来访问此上传文件的信息。$FILES['file1']也是一个数组,数组元素是上传文件的各种属性,具体说明如下。
• $FILES['file1']['Name']:客户端上传文件的名称。
• $FILES['file1']['type']:文件的 MIME 类型,需要浏览器提供对此类型的支持,如image/gif等。
• $FILES['file1']['size']:已上传文件的大小,单位是字节。
• $FILES['file1']['tmp_name']:文件被上传后,在服务器端保存的临时文件名。
• $FILES['file1']['error']:上传文件过程中出现的错误号,错误号是一个整数,其取值如表5-8所示。
表5-8 上传文件过程中出现的错误
【例5-6】 设计在upload.html中指定的上传文件处理脚本upfile.php,代码如下:
<html>
<head>
<title>文件上传</title>
</head>
<body>
<font style='font-family:宋体; font-size: 9pt'>
<?PHP
//检查上传文件的目录
$upload_dir = getcwd() . "\\images\\";
//如果目录不存在,则创建
if(!is_dir($upload_dir))
mkdir($upload_dir);
//此函数用于根据当前系统时间自动生成上传文件名
function makefilename() {
//获取当前系统时间,生成文件名
$curtime = getdate();
$filename =$curtime['year'] . $curtime['mon'] . $curtime['mday'] . $curtime['hours'] . $curtime['minutes'] . $curtime['seconds'] . ".jpeg";
Return $filename;
}
$newfilename = makefilename();
$newfile = $upload_dir . $newfilename;
if(file_exists($_FILES['file1']['tmp_name'])) {
move_uploaded_file($_FILES['file1']['tmp_name'], $newfile);
}
else {
echo("error");
}
echo("客户端文件名:" . $_FILES['file1']['name'] . "<BR>");
echo("文件类型:" . $_FILES['file1']['type'] . "<BR>");
echo("文件大小:" . $_FILES['file1']['size'] . "<BR>");
echo("服务器端临时文件名:" . $_FILES['file1']['tmp_name'] . "<BR>");
// echo( $_FILES['file1']['error'] . "<BR>");
echo("上传后新的文件名:" . $newfile . "<BR>");
?>
文件上传成功 [ <a href=# onclick=history.go(-1)>继续上传</a> ]
<BR><BR>下面是上传的图片文件:<BR><BR>
<img border="0" src="images/<?PHP echo($newfilename); ?>">
</font>
</body>
</html>
程序的执行过程如下。
1.判断保存上传文件的目录images是否存在
本实例指定保存上传文件的目录为images。getcwd()函数用于返回当前工作目录。
程序使用is_dir()函数判断保存上传文件的目录images是否存在,如果不存在,则使用mkdir()创建之。is_dir()函数的语法如下:
bool is_dir ( string $filename )
如果文件名 filename 存在并且为目录则返回 TRUE。如果 filename 是一个相对路径,则按照当前工作目录检查其相对路径。
mkdir()函数用于创建目录,其基本语法如下:
bool mkdir ( string $pathname)
如果创建成功则返回TRUE,否则返回FALSE。
2.调用makefilename()函数生成新的文件名
本例约定每个上传的文件都保存在\images目录下。为了防止出现同名文件,覆盖原来上传的文件,程序中提供了一个 makefilename()函数,它的功能是根据当前的系统时间来生成文件名。本例中要求用户上传以jpeg为扩展名的文件。
getdate()函数返回一个表示当前系统时间数组,该数组包含如表5-9所示的键。
表5-9 getdate()函数返回数组中包含的键
续表
makefilename()函数根据getdate()函数返回的数组来生成保存上传文件的文件名。
3.保存上传文件
程序首先调用 file_exists()函数判断$_FILES['file1']['tmp_name']中保存的临时文件是否存在,如果存在,则表示服务器已经成功接收到了上传的文件,并保存在临时目录下;然后调用move_uploaded_file()函数将上传文件移动至\images目录下。
file_exists()函数的语法如下:
bool file_exists( string $filename )
如果由filename指定的文件或目录存在则返回 TRUE,否则返回 FALSE。
move_uploaded_file()函数的语法如下:
bool move_uploaded_file( string $filename, string $destination )
函数检查并确保由filename指定的文件是合法的上传文件(即通过PHP的HTTP POST上传机制所上传的)。如果文件合法,则将其移动为由destination指定的文件。
如果filename不是合法的上传文件,不会出现任何操作,move_uploaded_file()将返回FALSE。
如果 filename 是合法的上传文件,但出于某些原因无法移动,不会出现任何操作, move_uploaded_file()将返回FALSE。
如果文件移动成功,则返回TRUE。
4.显示上传文件的信息
最后,程序显示$_FILES['file1']中各项上传文件的信息。
使用 HTML 语句<a href=# onclick=history. go(-1) >…</a>来显示“继续上传”超链接。history.go(-1)是JavaScript语句,表示返回上一页。
使用 <img border="0" src="images/<?PHP echo($newfilename); ?>">语句显示新上传的图片文件。文件名由PHP程序输出。
如果图片文件正确显示,则表示上传成功,如图5-17所示。
图5-17 文件上传成功
5.4.2 配置文件上传
PHP提供了一组参数,可以对文件上传进行配置。通常情况下,保持默认配置即可以实现文件上传的功能。但如果有特殊需求(如上传较大的文件),则需要修改配置文件。
可以在php.ini中对文件上传参数进行配置,主要的参数说明如下。
1.max_execution_time
指定每个脚本最大的执行时间,单位是秒。默认情况下是30秒,如果要上传大文件,则可以根据实际情况增加此配置值。
2.post_max_size
指定PHP可以接收的最大提交数据的大小,单位是MB,默认值为8MB。
3.file_uploads
是否允许文件上传,默认值为On,即支持文件上传。如果设置为Off,则不支持文件上传功能。
4.upload_tmp_dir
设置保存上传文件的临时目录。如果不设置,则使用系统默认的临时文件目录。
5.upload_max_filesize
允许上传的文件大小,单位是 MB,默认值为 2MB。此值通常比 post_max_size 要小。如果要上传较大的文件,可以修改此配置项。
修改php.ini后,需要重新启动Apache才能生效。