PHP 中的文件读写与上传

0 阅读2分钟

PHP 中的文件读写与上传

判断与信息获取

判断文件

函数说明返回值
file_exists($path)判断文件或目录是否存在bool
is_file($path)判断是否是文件bool
is_dir($path)判断是否是目录bool
is_readable($path)判断是否可读bool
is_writable($path)判断是否可写bool
<?php
$file = './config.php';
$dir = './logs';

// 1. 判断文件是否存在
if (file_exists($file)) {
    echo "文件存在<br>";
    
    // 2. 判断是否是文件
    if (is_file($file)) {
        echo "这是一个文件<br>";
    }
}

// 3. 判断目录是否存在且可写
if (is_dir($dir) && is_writable($dir)) {
    echo "目录存在且可写<br>";
}
?>

获取文件信息

函数说明
filesize($path)获取文件大小(字节)
filemtime($path)获取文件最后修改时间(时间戳)
pathinfo($path)获取文件路径信息(目录、文件名、后缀)
<?php
$file = './photo.jpg';

// 获取文件大小
$size = filesize($file);
echo "文件大小:" . round($size / 1024, 2) . " KB<br>";

// 获取最后修改时间
$mtime = filemtime($file);
echo "最后修改时间:" . date('Y-m-d H:i:s', $mtime) . "<br>";

// 获取路径信息
$info = pathinfo($file);
echo "文件名:" . $info['filename'] . "<br>";
echo "后缀名:" . $info['extension'] . "<br>";
echo "目录:" . $info['dirname'] . "<br>";
?>

文件读写

简单方式:file_get_contents() / file_put_contents()

// 读取文件内容到字符串
$content = file_get_contents(string $filename);

// 将字符串写入文件(返回写入的字节数)
file_put_contents(string $filename, mixed $data, int $flags = 0);

读取 JSON 配置文件

<?php
// 假设 config.json 内容:{"db_host": "localhost", "db_user": "root"}
$json = file_get_contents('./config.json');
$config = json_decode($json, true); // 转数组

echo "数据库主机:" . $config['db_host']; // 数据库主机:localhost
?>

写入日志文件(追加模式)

<?php
// 日志内容
$log = "[".date('Y-m-d H:i:s')."] 用户登录成功\n";

// FILE_APPEND:追加写入(不覆盖原内容)
// LOCK_EX:独占锁(防止多人同时写入导致数据混乱)
file_put_contents('./logs/app.log', $log, FILE_APPEND | LOCK_EX);
?>

底层方式:fopen() / fwrite() / fclose()

当你需要逐行读取写入大文件更精细的控制时,使用这组函数。

// 打开文件,返回资源句柄
$handle = fopen(string $filename, string $mode);

// 写入文件
fwrite(resource $handle, string $data);

// 读取一行
$line = fgets(resource $handle);

// 关闭文件
fclose(resource $handle);

常用 mode 参数

模式说明
r只读,指针在开头
w只写,清空文件内容,指针在开头
a追加,指针在末尾
r+读写,指针在开头

逐行读取大文件(不占内存)

<?php
// 打开一个大文件(比如 1GB 的日志)
$handle = fopen('./large_file.log', 'r');

if ($handle) {
    // 逐行读取,直到文件结束
    while (($line = fgets($handle)) !== false) {
        // 处理每一行(比如过滤错误日志)
        if (strpos($line, 'ERROR') !== false) {
            echo "发现错误:" . $line . "<br>";
        }
    }
    fclose($handle);
}
?>

目录操作:创建、删除与遍历

函数说明
mkdir($path)创建目录
rmdir($path)删除空目录
unlink($path)删除文件

递归创建多级目录

<?php
// 要创建的目录路径
$dir = './uploads/2023/10/01';

// mkdir 第三个参数 true:递归创建父目录
if (!is_dir($dir)) {
    mkdir($dir, 0755, true);
    echo "目录创建成功";
}
?>

遍历目录

  1. scandir()(简单遍历,适合单层目录)
<?php
$dir = './uploads';

// 获取目录下所有文件和目录(包含 . 和 ..)
$files = scandir($dir);

// 遍历并过滤掉 . 和 ..
foreach ($files as $file) {
    if ($file != '.' && $file != '..') {
        // 判断是文件还是目录
        $type = is_file($dir . '/' . $file) ? '文件' : '目录';
        echo $type . ":" . $file . "<br>";
    }
}
?>
  1. RecursiveDirectoryIterator(递归遍历,适合多层目录)
<?php
$dir = './uploads';

// 使用递归迭代器
$iterator = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
    RecursiveIteratorIterator::SELF_FIRST
);

foreach ($iterator as $file) {
    // $file 是 SplFileInfo 对象
    echo "路径:" . $file->getPathname() . " - 大小:" . $file->getSize() . " 字节<br>";
}
?>

文件上传 :图片上传

文件上传是 Web 开发的经典需求,PHP 通过 $_FILES 超全局变量和 move_uploaded_file() 函数处理。

<form action="upload.php" method="post" enctype="multipart/form-data">
    选择图片:<input type="file" name="avatar" accept="image/*">
    <input type="submit" value="上传">
</form>
<?php
// 检查是否有上传错误
if ($_FILES['avatar']['error'] !== UPLOAD_ERR_OK) {
    exit('上传错误:' . $_FILES['avatar']['error']);
}

// 定义上传目录
$uploadDir = './uploads/';
if (!is_dir($uploadDir)) {
    mkdir($uploadDir, 0755, true);
}

// 获取文件后缀,生成唯一文件名
$ext = pathinfo($_FILES['avatar']['name'], PATHINFO_EXTENSION);
$filename = uniqid() . '.' . $ext;
$destPath = $uploadDir . $filename;

// 验证文件类型(简单验证:只允许图片)
$allowedTypes = ['jpg', 'jpeg', 'png', 'gif'];
if (!in_array(strtolower($ext), $allowedTypes)) {
    exit('只允许上传图片文件');
}

// 验证文件大小(限制 2MB)
if ($_FILES['avatar']['size'] > 2 * 1024 * 1024) {
    exit('文件大小不能超过 2MB');
}

// 从临时目录移动到目标目录
if (move_uploaded_file($_FILES['avatar']['tmp_name'], $destPath)) {
    echo "上传成功!文件路径:" . $destPath;
} else {
    exit('文件移动失败');
}
?>