一、相关知识
一、文件上传原理简介
将客户端的文件上传到服务器端,再将服务器端的临时文件移动到指定目录即可。
二、$_FILES 预定义变量解析
1、name:上传文件的名字;
2、type:上传文件的 MIME 类型;
3、tmp_name:上传到服务器上的临时文件名;
4、size:上传文件的大小;
5、error:上传文件的错误号;
三、服务器端相关配置
1、file_uploads=On,支持 HTTP 上传;
2、upload_tmp_dir= ,临时文件保存目录;
3、upload_max_filesize=2M,允许上传文件的最大值;
4、max_file_uploads=20,允许一次上传的最大文件数;
5、post_max_size=8M,POST方式发送数据的最大值;
6、max_execution_time=-1,设置了脚本被解析器终止之前允许的最大执行时间,单位为秒,防止程序写得不好而占尽服务器资源;
7、max_input_time=60,脚本解析输入数据允许的最大时间,单位是秒;
8、max_input_nesting_level=64,设置输入变量的嵌套深度;9、max_input_vars=1000,接受多少输入变量(限制分别应用于$_GET、$_POST和$_COOKIE 超全局变量)指令的使用减轻了以哈希碰撞来进行拒绝服务攻击的可能性。如有超过指令指定数量的变量,将会导致 E_WARNING 的产生,更多的输入变量将会从请求中截断;
10、memory_limit=128M,最大单线程的独立内存使用量。也就是一个 web 请求,给予线程最大的内存使用量的定义。
四、错误信息说明
1、UPLOAD_ERR_OK:其值为 0,没有错误发生,文件上传成功;
2、UPLOAD_ERR_INI_SIZE:其值为 1,上传的文件超过 php.ini 中 upload_max_filesize 选项限制的值;
3、UPLOAD_ERR_FORM_SIZE:其值为 2,上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值;
4、UPLOAD_ERR_PARTIAL:其值为 3,文件只有部分被上传;
5、UPLOAD_ERR_NO_FILE:其值为 4,没有文件被上传;
6、UPLOAD_ERR_NO_TMP_DIR:其值为 6,没有找到临时文件夹;
7、UPLOAD_ERR_CANT_WRITE:其值为 7,文件写入失败;
8、UPLOAD_ERR_EXTENSION:其值为 8,上传的文件被 PHP 扩展程序中断。
二、实战开发
1、上传文件类:Upload.php
<?php
define('MAX_SIZE', 1); // 允许上传文件大小,默认为 1M 大小
define('FLAG',false); // 检验上传图片是否为真实图片,默认为关闭
class Upload {
/** 私有化构造类 */
private function __construct(){}
/** 允许上传的文件类型 */
public static $allowExt = array('jpeg','jpg','png','gif');
/**
* 构建上传文件信息
* @param [type] $fileInfos 上传文件信息
* @return 返回重构文件的信息
*/
public static function getFiles($fileInfos) {
$i = 0;
foreach ($fileInfos as $file) {
if(is_string($file['name'])) {
$files[$i] = $file;
$i++;
}elseif (is_array($file['name'])) {
foreach ($file['name'] as $key => $value) {
$files[$i]['name'] = $file['name'][$key];
$files[$i]['type'] = $file['type'][$key];
$files[$i]['tmp_name'] = $file['tmp_name'][$key];
$files[$i]['error'] = $file['error'][$key];
$files[$i]['size'] = $file['size'][$key];
$i++;
}
}
}
foreach ($files as $file) {
if(!$file['name']) continue;
self::uploadFile($file);
}
}
/**
* 针对单文件、多文件上传
* @param [type] $fileInfo 重新构建好的文件信息
* @param string $path 上传文件的目录
* @param [type] $flag 是否开启检验图片为真实图片
* @param [type] $max_size 允许上传文件的大小
* @param array $allowExt 允许上传文件的类型
*/
public static function uploadFile($fileInfo,$path='./uploads',$flag=FLAG,$max_size=MAX_SIZE) {
/** 限制文件上传大小,默认 1M */
$maxSize = $max_size * 1024 * 1024;
/** 判断错误号 */
if($fileInfo['error'] === UPLOAD_ERR_OK) {
/** 检测上传文件大小 */
if($fileInfo['size'] > $maxSize) {
echo $fileInfo['name'].' 上传文件过大'."<br />";
return ;
}
/** 获取上传文件扩展名 */
$ext = self::getExt($fileInfo['name']);
/** 检测上传文件的文件类型 */
if(!in_array($ext,self::$allowExt)) {
echo $fileInfo['name'].' 为非法文件类型'."<br />";
return ;
}
/** 检测是否是真实的图片类型 */
if($flag) {
if(!getimagesize($fileInfo['tmp_name'])) {
echo '不是真实图片类型'."<br />";
return ;
}
}
/** 检测文件是否是通过HTTP POST上传上来的 */
if(!is_uploaded_file($fileInfo['tmp_name'])) {
echo '文件不是通过HTTP POST方式上传上来的'."<br />";
return ;
}
/** 判断上传的目录是否存在,不存在则创建目录 */
if(!file_exists($path)) {
mkdir($path,0777,true);
chmod($path,0777);
}
/** 获取唯一序列字符串 */
$uniName = self::getUniName();
/** 上传文件目录 */
$destination = $path.'/'.$uniName.'.'.$ext;
if(!move_uploaded_file($fileInfo['tmp_name'],$destination)) {
echo '文件移动失败'."<br />";
return ;
}
echo $destination."上传文件成功! "."<br />";
}else {
/** 匹配错误信息 */
switch ($fileInfo ['error']) {
case 1 :
echo '上传文件超过了PHP配置文件中upload_max_filesize选项的值';
break;
case 2 :
echo '超过了表单MAX_FILE_SIZE限制的大小';
break;
case 3 :
echo '文件部分被上传';
break;
case 4 :
echo '没有选择上传文件';
break;
case 6 :
echo '没有找到临时目录';
break;
case 7 :
case 8 :
echo '系统错误';
break;
}
}
}
/**
* 获取文件名扩展
* @param [type] $filename [description]
* @return [type] 返回文件名扩展
*/
public static function getExt($filename) {
$ext = strtolower(pathinfo($filename,PATHINFO_EXTENSION));
return $ext;
}
/**
* 返回唯一序列字符串
* @return [type] [description]
*/
public static function getUniName() {
return md5(uniqid(microtime(true),true));
}
}
2、使用方法
<?php
/** 引入文件上传类 */
require_once 'Upload.php';
/** 获取表单提交过来的文件信息,调用文件上传方法,上传文件*/
Upload::getFiles($_FILES);