Получение данных о файле в PHP: практические примеры
Работа с файловой системой в PHP часто требует извлечения различных атрибутов файлов: расширения, размера, времени изменения, MIME-типа. Ниже рассмотрены основные подходы с примерами кода.
Основное решение: функция pathinfo
Как получить полную информацию о пути к файлу, включая расширение?
Функция pathinfo возвращает массив с элементами dirname, basename, extension (если есть) и filename. Она работает с любой строкой пути, не требуя существования файла.
<?php
$path = '/var/www/html/image.jpg';
$info = pathinfo($path);
print_r($info);
?>
Array
(
[dirname] => /var/www/html
[basename] => image.jpg
[extension] => jpg
[filename] => image
)
Для извлечения только расширения используется константа PATHINFO_EXTENSION:
<?php
echo pathinfo($path, PATHINFO_EXTENSION); // jpg
?>
Проблема: pathinfo не проверяет, существует ли файл. Если указать несуществующий путь, результат все равно будет получен на основе строки. Для проверки существования следует вызывать file_exists.
Как извлечь расширение без использования pathinfo?
В некоторых ситуациях требуется получить расширение вручную, например, для обратной совместимости. Используются функции explode и strrchr.
Пример с explode:
<?php
$filename = 'document.pdf';
$parts = explode('.', $filename);
$ext = end($parts);
echo $ext; // pdf
?>
Пример с strrchr:
<?php
$ext = substr(strrchr($filename, '.'), 1);
echo $ext; // pdf
?>
Проблема: explode не учитывает файлы без расширения или с несколькими точками (например, 'file.tar.gz' вернет 'gz', хотя искомая часть может быть 'tar.gz'). strrchr берет последнюю часть. Для архивированных файлов лучше использовать pathinfo или комбинировать методы.
Как получить расширение через объектно-ориентированный интерфейс SplFileInfo?
Класс SplFileInfo предоставляет методы для получения информации о реальном файле (существующем). Расширение извлекается методом getExtension().
<?php
$file = new SplFileInfo('/etc/passwd');
echo $file->getExtension(); // пустая строка (нет расширения)
$file2 = new SplFileInfo('script.php');
echo $file2->getExtension(); // php
?>
Проблема: Конструктор SplFileInfo не проверяет существование файла, но методы (например, getSize) вызовут ошибку, если файл не существует. getExtension просто анализирует имя.
Как определить MIME-тип и реальное расширение файла?
Расширение по имени не всегда соответствует содержимому. Для точного определения типа используется finfo (File Information) или устаревшая функция mime_content_type.
<?php
$finfo = finfo_open(FILEINFO_MIME_TYPE);
echo finfo_file($finfo, 'image.png'); // image/png
finfo_close($finfo);
?>
image/png
Проблема: Для работы finfo требуется расширение fileinfo (включено по умолчанию в PHP 5.3+). Для удаленных файлов (URL) finfo не работает напрямую, требуется скачать содержимое.
Как получить размер, дату создания и изменения файла?
Помимо расширения, часто нужны метаданные. Функции filesize, filemtime, filectime возвращают размер и временные метки.
<?php
$file = 'data.txt';
if (file_exists($file)) {
echo 'Size: ' . filesize($file) . ' bytes' . PHP_EOL;
echo 'Last modified: ' . date('Y-m-d H:i:s', filemtime($file));
}
?>
Size: 1234 bytes Last modified: 2025-04-01 12:00:00
Проблема: filesize и другие функции кэшируют результаты, если не используется clearstatcache(). При многократном вызове в одном скрипте для файла, который может измениться, следует очищать кэш.
Продвинутые примеры
Рекурсивный обход директории с выводом полной информации
Пример демонстрирует обход всех файлов в указанной директории (рекурсивно) с получением размера, расширения и MIME-типа.
<?php
function fileInfoRecursive($dir) {
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS)
);
foreach ($iterator as $fileinfo) {
if ($fileinfo->isFile()) {
echo $fileinfo->getPathname() . PHP_EOL;
echo ' Size: ' . $fileinfo->getSize() . ' bytes' . PHP_EOL;
echo ' Extension: ' . $fileinfo->getExtension() . PHP_EOL;
echo ' MIME: ' . mime_content_type($fileinfo->getPathname()) . PHP_EOL;
}
}
}
fileInfoRecursive('/path/to/directory');
?>
/path/to/directory/file1.txt Size: 100 bytes Extension: txt MIME: text/plain ...
Проверка загруженного файла (расширение и MIME)
Код обрабатывает файл, переданный через форму, проверяет расширение и фактический MIME-тип.
<?php
// Предполагается, что файл загружен через форму
$uploadedFile = $_FILES['file'];
$ext = pathinfo($uploadedFile['name'], PATHINFO_EXTENSION);
$allowedExts = ['jpg', 'png', 'gif'];
if (in_array(strtolower($ext), $allowedExts)) {
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $uploadedFile['tmp_name']);
finfo_close($finfo);
if (strpos($mime, 'image/') === 0) {
echo 'Файл является изображением: ' . $uploadedFile['name'];
} else {
echo 'MIME-тип не соответствует изображению';
}
} else {
echo 'Недопустимое расширение';
}
?>
Файл является изображением: photo.jpg
Извлечение расширения из URL
Позволяет получить расширение файла, указанного в URL, с учётом возможных параметров запроса.
<?php
$url = 'https://example.com/download/file.zip?param=1';
$basename = basename(parse_url($url, PHP_URL_PATH));
$ext = pathinfo($basename, PATHINFO_EXTENSION);
echo $ext; // zip
?>
zip
Использование регулярного выражения
Альтернативный способ извлечения расширения с помощью регулярного выражения.
<?php
$filename = 'archive.tar.bz2';
if (preg_match('/\.([a-zA-Z0-9]+)$/', $filename, $matches)) {
echo $matches[1]; // bz2
}
?>
bz2
Работа с файлами, имеющими множественные расширения
Обработка случаев, когда файл содержит несколько точек (например, .tar.gz).
<?php
$filename = 'backup.tar.gz';
// Извлечение последнего расширения
echo pathinfo($filename, PATHINFO_EXTENSION); // gz
// Извлечение первого расширения (например, tar)
$parts = explode('.', $filename);
if (count($parts) > 2) {
echo $parts[count($parts)-2]; // tar
}
?>
gz tar
Получение информации о символической ссылке
Определение цели ссылки и её расширения.
<?php
$link = '/usr/local/bin/php';
if (is_link($link)) {
$target = readlink($link);
echo "Ссылка $link ведёт на $target" . PHP_EOL;
$real = realpath($link);
echo "Реальный путь: $real" . PHP_EOL;
$info = new SplFileInfo($link);
echo "Расширение цели: " . $info->getExtension();
}
?>
Ссылка /usr/local/bin/php ведёт на /usr/local/bin/php8.3 Реальный путь: /usr/local/bin/php8.3 Расширение цели: (пусто)