PHP实现文件上传的原理已经在上面做了详细介绍,本节将对文件上传程序做必要的扩展,实现完整的文件上传程序。其中,upload.html文件是客户端程序,用来存储上传表单的JavaScript代码;upload.php文件是服务端的文件上传程序,用来处理客户端提交过来的上传文件。
1. 上传文件的客户端类型检测
文件上传程序的作用是对客户端提交的文件类型进行检测和过滤,这样可以有效地保护系统安全,类型检测代码如下:
header("content-Type: text/html; charset=utf-8"); $uptypes=array('image/jpg', //上传文件类型列表 'image/jpeg', 'image/png', 'image/pjpeg', 'image/gif', 'image/bmp', 'application/x-shockwave-flash', 'image/x-png', 'application/msword', 'audio/x-ms-wma', 'audio/mp3', 'application/vnd.rn-realmedia', 'application/x-zip-compressed', 'application/octet-stream'); $max_file_size=20000000; //上传文件大小限制, 单位BYTE $path_parts=pathinfo($_SERVER['PHP_SELF']); //取得当前路径 $destination_folder="up/"; //上传文件路径 $imgpreview=1; //是否生成预览图(1为生成,其他为不生成); $imgpreviewsize=1/2; //缩略图比例
【代码解读】
上面这段代码定义了允许上传的文件类型,也定义了其他辅助变量,如文件尺寸显示变量、系统路径变量、缩略图预览等变量。
2. 上传文件的服务器端处理
上传客户端文件(upload.html)中定义了getFileSize(filename)函数,它的作用是对上传的文件尺寸在客户端进行验证。由于客户端程序的各种限制,不能对上传文件做更多地判断和检测,这部分工作只能交给服务器端的PHP脚本文件来完成。
现在打开upload.php文件,完成类型判断、异常处理、信息提示、缩略图(仅限图片文件)等功能,核心代码如下:
<?/*功能:上传文件检测程序 */ $file=$_FILES['userfile']; if($max_file_size < $file["size"]) //检查文件大小 { echo "<font color='red'>文件太大!</font>"; exit; } if(!in_array($file["type"], $uptypes)) //检查文件类型 { echo "<font color='red'>不能上传此类型文件!</font>"; exit; } //检查上传目录是否存在,如果不存在则创建 if(!file_exists($destination_folder)){ mkdir($destination_folder); } $filename=$file["tmp_name"]; $image_size = getimagesize($filename); $pinfo=pathinfo($file["name"]);//pathinfo() 函数以数组的形式返回关于文件路径的信息。[dirname]: 目录路径,[basename]: 文件名,[extension]: 文件后缀名,[filename]: 不包含后缀的文件名 $ftype=$pinfo["extension"]; $destination = $destination_folder.time().".".$ftype; $fname = time().".".$ftype; if (file_exists($destination) && $overwrite != true) { echo "<font color='red'>同名文件已经存在了!</a>"; exit; } //移动文件异常处理 if(!move_uploaded_file ($filename, $destination)) { echo "<font color='red'>移动文件出错!</a>"; exit; }else{ //添加写入数据库的部分 // 创建数据库连接 $con = mysqli_connect('localhost', 'root', 'root') or die('Could not connect: ' . mysqli_error()); //echo 'Connected successfully'; $db=mysqli_select_db($con,'download'); if (!$db){ die ("Can\'t use download : " . mysqli_error()); }else{ // 将用户信息插入数据库的user表 $sql = "INSERT INTO `download`.`f_detail` (`id` ,`filename` ,`des` ,`fsize` ,`ftype` ,`utime` )VALUES (NULL ,'".$fname."' , '', '".$file["size"]."', '".$file["type"]."',NOW());"; $result =mysqli_query($con,$sql); if (!$result) { // 释放结果集 mysqli_free_result($con,$result); // 关闭连接 mysqli_close($con,$db); echo '数据记录插入失败!'; exit; } } } $pinfo=pathinfo($destination); $fname=$pinfo["basename"]; echo "<table><tr><td>上传文件地址:http://".$_SERVER['SERVER_NAME'].$path_parts["dirname"]."/".$destination_folder.$fname."</td></tr></table>"; echo " 宽度:".$image_size[0]; echo " 长度:".$image_size[1]; if($watermark==1) { $iinfo=getimagesize($destination,$iinfo); $nimage=imagecreatetruecolor($image_size[0],$image_size[1]); $white=imagecolorallocate($nimage,255,255,255); $black=imagecolorallocate($nimage,0,0,0); $red=imagecolorallocate($nimage,255,0,0); imagefill($nimage,0,0,$white); switch ($iinfo[2]) { case 1: $simage =imagecreatefromgif($destination); break; case 2: $simage =imagecreatefromjpeg($destination); break; case 3: $simage =imagecreatefrompng($destination); break; case 6: $simage =imagecreatefromwbmp($destination); break; default: die("<font color='red'>不能上传此类型文件!</a>"); exit; } imagecopy($nimage,$simage,0,0,0,0,$image_size[0],$image_size[1]); imagefilledrectangle($nimage,1,$image_size[1]-15,80,$image_size[1],$white); switch ($iinfo[2]) { case 1: //imagegif($nimage, $destination); imagejpeg($nimage, $destination); break; case 2: imagejpeg($nimage, $destination); break; case 3: imagepng($nimage, $destination); break; case 6: imagewbmp($nimage, $destination); //imagejpeg($nimage, $destination); break; } //覆盖原上传文件 imagedestroy($nimage); imagedestroy($simage); } if($imgpreview==1) { echo "<br>图片预览:<br>"; echo "<a href=\"".$destination."\" target='_blank'><img src=\"".$destination."\" width=".($image_size[0]*$imgpreviewsize)." height=".($image_size[1]*$imgpreviewsize); echo " alt=\"图片预览:\r文件名:".$fname."\r上传时间:".date('m/d/Y h:i')."\" border='0'></a>"; } ?>
修改后的upload.php程序可以完成将文件上传到指定的目录中的功能。当然,现在只是将文件上传到服务器的制定目录中去了,这样的文件凌乱且没有意义。
3. 将上传文件信息归档到数据库
上一节已经在数据库中创建了f_detail表,用来将上传文件信息做归档和记录。下面写一段SQL语句,作用是当文件上传成功时向数据库中写入文件的信息,SQL语句如下:
INSERTINTO 'download'.'f detail'('id’,'filename','des','fsize'1'ftype','utime’)VALUES(NULL, $filename, Sdes, $fsize,$ftype,Sutime);
下面打开upload.php文件,将信息写入部分代码添加到程序中,需要添加的代码如下:
<?php if(!move_uploaded_file ($filename, $destination)) { echo "<font color='red'>移动文件出错!</a>"; exit; }else{ //添加写入数据库的部分 // 创建数据库连接 $con = mysqli_connect('localhost', 'root', 'root') or die('Could not connect: ' . mysqli_error()); //echo 'Connected successfully'; $db=mysqli_select_db('download',$con); if (!$db){ die ("Can\'t use download : " . mysqli_error()); }else{ // 将用户信息插入数据库的user表 $sql = "INSERT INTO `download`.`f_detail` (`id` ,`filename` ,`des` ,`fsize` ,`ftype` ,`utime` )VALUES (NULL ,'".$fname."' , '', '".$file["size"]."', '".$file["type"]."',NOW());"; $result =mysqli_query($sql); if (!$result) { // 释放结果集 mysqli_free_result($result); // 关闭连接 mysqli_close($db); echo '数据记录插入失败!'; exit; } } } ?>
注意:SQL语言中有很多内部函数,例如上面的代码中出现的now()函数,其含义是在获得当前系统时间对应数据库字段的datetime()类型,这样就减少了用PHP来处理时间的步骤,提高了效率。
通过以上3个步骤,完成了一个完整的文件上传程序。读者可以根据自己的需要对这个程序进行改造,添加更多的功能。这个核心程序所展示的内部流程是任何与上传相关的程序共同的设计思路。