特殊变量
1. $_FILES
超全局变量
$_FILES
是 PHP 中用于处理文件上传的超全局数组变量,它包含了通过 HTTP POST 方法上传的所有文件信息。
(1)基本结构
当表单使用 enctype="multipart/form-data"
并且有文件上传字段时,$_FILES
数组会包含如下结构的元素:
$_FILES = [
'input_name' => [
'name' => 'filename.ext', // 原始文件名
'type' => 'mime/type', // 文件 MIME 类型
'tmp_name' => '/tmp/phpXxXxX', // 服务器上的临时文件路径
'error' => 0, // 错误代码(0表示无错误)
'size' => 12345 // 文件大小(字节)
]
];
各字段说明
name
- 客户端上传文件的原始名称
- 示例:
'example.jpg'
type
- 浏览器提供的 MIME 类型
- 示例:
'image/jpeg'
- 注意: 此值可以被伪造,不应单独用于验证
tmp_name
- 文件上传后在服务器上的临时存储路径
- 示例:
'/tmp/php5D.tmp'
error
- 错误代码(整型),常见值:
UPLOAD_ERR_OK
(0) - 无错误UPLOAD_ERR_INI_SIZE
(1) - 超过 php.ini 中的大小限制UPLOAD_ERR_FORM_SIZE
(2) - 超过表单中 MAX_FILE_SIZE 限制UPLOAD_ERR_PARTIAL
(3) - 文件只有部分被上传UPLOAD_ERR_NO_FILE
(4) - 没有文件被上传UPLOAD_ERR_NO_TMP_DIR
(6) - 找不到临时文件夹UPLOAD_ERR_CANT_WRITE
(7) - 写入磁盘失败UPLOAD_ERR_EXTENSION
(8) - PHP 扩展阻止了上传
- 错误代码(整型),常见值:
size
- 上传文件的大小(字节)
- 示例:
102400
(100KB)
(2)使用示例
基本文件上传处理
if ($_FILES['userfile']['error'] === UPLOAD_ERR_OK) {
$tmp_name = $_FILES['userfile']['tmp_name'];
$name = basename($_FILES['userfile']['name']);
move_uploaded_file($tmp_name, "/uploads/$name");
}
多文件上传处理
当使用多文件上传(如 <input type="file" name="files[]" multiple>
)时:
foreach ($_FILES['files']['error'] as $key => $error) {
if ($error === UPLOAD_ERR_OK) {
$tmp_name = $_FILES['files']['tmp_name'][$key];
$name = basename($_FILES['files']['name'][$key]);
move_uploaded_file($tmp_name, "/uploads/$name");
}
}
(3)安全注意事项
永远不要信任
$_FILES['...']['name']
- 客户端可以发送任意文件名,包括恶意路径如
../../../etc/passwd
- 客户端可以发送任意文件名,包括恶意路径如
验证文件内容
- 不要依赖
$_FILES['...']['type']
,因为它可以被伪造 - 使用
finfo_file()
或文件头检查实际文件类型
- 不要依赖
使用
move_uploaded_file()
- 此函数会额外检查文件是否是通过 HTTP POST 上传的
设置合理限制
- 在 php.ini 中配置:ini
upload_max_filesize = 2M post_max_size = 3M
- 在 php.ini 中配置:
处理错误
- 总是检查
$_FILES['...']['error']
的值
- 总是检查
(4)完整安全示例
$upload_dir = '/path/to/safe/directory/';
$allowed_types = ['image/jpeg', 'image/png'];
$max_size = 1024 * 1024; // 1MB
if ($_FILES['file']['error'] !== UPLOAD_ERR_OK) {
die("上传错误: " . $_FILES['file']['error']);
}
// 验证文件类型
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $_FILES['file']['tmp_name']);
finfo_close($finfo);
if (!in_array($mime, $allowed_types)) {
die("不允许的文件类型");
}
// 验证文件大小
if ($_FILES['file']['size'] > $max_size) {
die("文件太大");
}
// 生成安全文件名
$ext = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
$filename = uniqid() . '.' . $ext;
// 移动文件
if (!move_uploaded_file(
$_FILES['file']['tmp_name'],
$upload_dir . $filename
)) {
die("文件保存失败");
}
echo "文件上传成功!";
2.$_SERVER
超全局变量详解
$_SERVER
是 PHP 中一个非常重要的超全局变量,它包含了服务器和执行环境的信息。这些信息包括头部信息(header)、路径(path)和脚本位置(script locations)等。
(1)基本介绍
$_SERVER
是一个包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等信息的数组。这个数组中的项目由 Web 服务器创建。
(2)常用 $_SERVER 元素
服务器信息
$_SERVER['SERVER_NAME']
- 当前运行脚本所在的服务器的主机名$_SERVER['SERVER_SOFTWARE']
- 服务器标识字符串$_SERVER['SERVER_PROTOCOL']
- 请求页面时通信协议的名称和版本$_SERVER['SERVER_ADDR']
- 服务器 IP 地址$_SERVER['SERVER_PORT']
- 服务器使用的端口
请求信息
$_SERVER['REQUEST_METHOD']
- 访问页面使用的请求方法(如 GET、POST 等)$_SERVER['REQUEST_URI']
- URI 用来指定要访问的页面$_SERVER['QUERY_STRING']
- 查询字符串(URL 中第一个问号 ? 之后的内容)$_SERVER['HTTP_REFERER']
- 引导用户代理到当前页的前一页的地址$_SERVER['HTTP_USER_AGENT']
- 用户代理字符串(浏览器信息)$_SERVER['REMOTE_ADDR']
- 浏览当前页面的用户的 IP 地址$_SERVER['REMOTE_PORT']
- 用户机器上连接到 Web 服务器所使用的端口号
脚本信息
$_SERVER['SCRIPT_FILENAME']
- 当前执行脚本的绝对路径$_SERVER['SCRIPT_NAME']
- 包含当前脚本的路径$_SERVER['PHP_SELF']
- 当前执行脚本的文件名$_SERVER['DOCUMENT_ROOT']
- 当前运行脚本所在的文档根目录
(3)使用示例
<?php
// 获取客户端IP地址
$ip = $_SERVER['REMOTE_ADDR'];
// 获取当前页面的完整URL
$url = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
// 获取用户浏览器信息
$browser = $_SERVER['HTTP_USER_AGENT'];
// 获取请求方法
$method = $_SERVER['REQUEST_METHOD'];
// 获取引荐来源(如果有)
$referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '直接访问';
echo "IP地址: $ip <br>";
echo "当前URL: $url <br>";
echo "浏览器: $browser <br>";
echo "请求方法: $method <br>";
echo "来源: $referer <br>";
?>
(4)注意事项
不是所有的
$_SERVER
元素在所有服务器上都可用,有些元素依赖于特定的服务器配置。$_SERVER
中的 HTTP_ 开头的元素(如HTTP_REFERER
)是由客户端发送的,可以被伪造,不应完全信任。某些元素如
PHP_SELF
可能包含用户输入,直接使用可能导致 XSS 攻击,应该先过滤:php$php_self = htmlspecialchars($_SERVER['PHP_SELF']);
在命令行模式下运行 PHP 时,
$_SERVER
的内容与在 Web 服务器环境下有很大不同。某些服务器变量在不同服务器(Apache、Nginx、IIS等)上可能有不同的名称或行为。
$_SERVER
是一个非常有用的变量,特别是在需要获取环境信息或处理 URL 时,但使用时应当注意安全性和跨服务器的兼容性问题。