Обзор файловых браузеров на PHP и их реализация

Раздел: PHP -> Файловые менеджеры и хостинг

Файловый браузер на PHP позволяет пользователю просматривать содержимое серверных директорий через веб-интерфейс. Такое решение часто используется в файловых менеджерах хостинг-панелей, системах управления контентом или для организации временного доступа к файлам. В статье рассматриваются различные подходы к реализации, начиная от простого скрипта и заканчивая интеграцией готовых библиотек. Примеры кода помогут разобраться в деталях и избежать типичных ошибок.

Основное решение: простой файловый браузер с навигацией

Самый простой и эффективный способ создать файловый браузер - использовать встроенные функции PHP для обхода директорий. Ниже представлен код, который выводит список файлов и папок в текущей директории, позволяет переходить по папкам и возвращаться назад. Решение безопасно, так как проверяет, что запрошенный путь является поддиректорией разрешенной корневой папки.


<?php
$root = '/var/www/files'; // корневая директория
$path = isset($_GET['dir']) ? realpath($root . '/' . $_GET['dir']) : $root;
if (!$path || strpos($path, $root) !== 0) {
    die('Недопустимый путь');
}
$items = scandir($path);
echo '<ul>';
foreach ($items as $item) {
    if ($item == '.' || $item == '..') continue;
    $fullPath = $path . '/' . $item;
    $relative = substr($fullPath, strlen($root)+1);
    if (is_dir($fullPath)) {
        echo '<li><a href="?dir=' . urlencode($relative) . '">' . htmlspecialchars($item) . '/</a></li>';
    } else {
        echo '<li>' . htmlspecialchars($item) . ' (' . filesize($fullPath) . ' байт)</li>';
    }
}
echo '</ul>';
if ($path != $root) {
    $parent = dirname($_GET['dir']);
    $parent = ($parent == '.') ? '' : $parent;
    echo '<a href="?dir=' . urlencode($parent) . '">Наверх</a>';
}
?>

Php file browser (файловый браузер на php)

Объяснение шагов:

  • Установка корневой директории $root - все операции ограничены ею.
  • Получение текущей директории из параметра dir, проверка через realpath и strpos для защиты от path traversal.
  • Использование scandir для получения списка файлов.
  • Вывод элементов: папки отображаются как ссылки, файлы - как текст с размером.
  • Ссылка «Наверх» для возврата в родительскую директорию.

Типичные ошибки:

  • Необработанный path traversal: злоумышленник может указать ?dir=../../etc/passwd. Решение - проверка, что разрешенный путь начинается с корневого.
  • Проблемы с кодировкой: имена файлов в UTF-8 могут некорректно отображаться. Используйте htmlspecialchars и убедитесь, что страница передает UTF-8.
  • Права доступа: скрипт может не иметь прав на чтение директории. Следует проверять is_readable и выводить сообщение об ошибке.

Как отобразить файлы в виде дерева с помощью рекурсии?

Для древовидного отображения подходит рекурсивный обход. Каждая папка раскрывается в зависимости от параметра. Пример:


function tree($dir, $root, $depth = 0) {
    $items = scandir($dir);
    echo '<ul>';
    foreach ($items as $item) {
        if ($item[0] == '.') continue;
        $path = $dir . '/' . $item;
        $relative = substr($path, strlen($root)+1);
        $indent = str_repeat('&nbsp;', $depth*4);
        if (is_dir($path)) {
            echo '<li>' . $indent . '<a href="?dir=' . urlencode($relative) . '">' . htmlspecialchars($item) . '/</a>';
            if (isset($_GET['expand']) && $_GET['expand'] == $relative) {
                tree($path, $root, $depth+1);
            }
            echo '</li>';
        } else {
            echo '<li>' . $indent . htmlspecialchars($item) . '</li>';
        }
    }
    echo '</ul>';
}

File storage php (хранение файлов в php)

Вызов: tree($root, $root) с передачей параметра expand для раскрытия нужной папки.

  • Большое количество папок может замедлить работу. Можно использовать кэширование.
  • Рекурсия может превысить лимит вложенности. Для глубоких деревьев применяют итеративный обход.

Как дать пользователю возможность загружать файлы на сервер?

Добавление формы загрузки с обработкой на PHP. Файлы сохраняются в текущую директорию.


<form method="post" enctype="multipart/form-data">
    <input type="file" name="file">
    <input type="submit" value="Загрузить">
</form>
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) {
    $target = $path . '/' . basename($_FILES['file']['name']);
    if (move_uploaded_file($_FILES['file']['tmp_name'], $target)) {
        echo 'Файл загружен';
    } else {
        echo 'Ошибка загрузки';
    }
}
?>

Php file manager (файловый менеджер на php)

  • Ограничение размера через php.ini (upload_max_filesize, post_max_size).
  • Проверка типа файла для безопасности: mime_content_type или расширение.
  • Перезапись существующих файлов - необходимо добавить проверку.

Как сделать навигацию по папкам без перезагрузки страницы?

AJAX запрос к файловому браузеру, который возвращает HTML. Пример на JavaScript (fetch):


function loadDir(dir) {
    fetch('browser.php?dir=' + encodeURIComponent(dir))
        .then(response => response.text())
        .then(html => {
            document.getElementById('filelist').innerHTML = html;
        });
}

Серверный код аналогичен основному, но возвращает только список, без всей страницы.

  • Необходимо корректно обрабатывать ошибки HTTP.
  • Поддержка истории браузера через pushState или hash.

Как быстро развернуть полнофункциональный файловый менеджер?

Готовая библиотека elFinder (на базе jQuery) предоставляет готовый интерфейс с drag-and-drop, редактированием, правами доступа. Подключение:


// elfinder.html
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/elfinder@2.1.57/css/elfinder.min.css">
<script src="//cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/elfinder@2.1.57/js/elfinder.min.js"></script>
<div id="elfinder"></div>
<script>
$('#elfinder').elfinder({
    url: 'php/connector.minimal.php'
});
</script>

Серверный коннектор обычно входит в состав elFinder. Настраивается корневая директория и права доступа.

  • Требуется jQuery и дополнительные ресурсы.
  • Необходимо настроить коннектор под свои нужды (аутентификация, ограничения).
  • Версии elFinder могут иметь уязвимости, следует обновлять.

Как ограничить доступ к файловому браузеру только для авторизованных пользователей?

Простая проверка сессии перед началом работы:


session_start();
if (!isset($_SESSION['user'])) {
    header('HTTP/1.0 403 Forbidden');
    exit('Доступ запрещен');
}
// далее код браузера

Для более гибкого управления можно использовать библиотеки аутентификации (например, PHP-Auth).

  • Не забывайте о защите от CSRF, если браузер выполняет изменения.
  • Хранение сессий должно быть безопасным.

Расширенные примеры реализации файлового браузера на PHP

Рекурсивный обход с сортировкой и фильтрацией

Пример

function listFilesRecursive($dir, $filter = null) {
    $iterator = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS)
    );
    $files = [];
    foreach ($iterator as $file) {
        if ($filter && !preg_match($filter, $file->getFilename())) continue;
        $files[] = $file->getPathname();
    }
    sort($files);
    return $files;
}
// Пример: $files = listFilesRecursive('/var/www/files', '/\.php$/');

Результат - массив с путями, отсортированный по имени. Можно дополнить группировкой по расширению.

Операции с файлами: переименование и удаление

Пример

// Переименование
if (isset($_POST['rename'], $_POST['old'], $_POST['new'])) {
    $old = $root . '/' . $_POST['old'];
    $new = $root . '/' . dirname($_POST['old']) . '/' . basename($_POST['new']);
    if (rename($old, $new)) {
        echo 'Успешно переименовано';
    } else {
        echo 'Ошибка переименования';
    }
}
// Удаление (только файлы или пустые папки)
if (isset($_POST['delete'])) {
    $target = $root . '/' . $_POST['delete'];
    if (is_file($target)) {
        unlink($target);
    } elseif (is_dir($target) && !(new FilesystemIterator($target))->valid()) {
        rmdir($target);
    } else {
        echo 'Папка не пуста';
    }
}

Важно проверять права и путь, чтобы не выйти за корневую директорию.

Генерация миниатюр изображений

Пример

function thumbnail($path, $width = 100, $height = 100) {
    list($w, $h) = getimagesize($path);
    $src = imagecreatefromstring(file_get_contents($path));
    $thumb = imagecreatetruecolor($width, $height);
    imagecopyresampled($thumb, $src, 0, 0, 0, 0, $width, $height, $w, $h);
    ob_start();
    imagejpeg($thumb);
    return ob_get_clean();
}
// Вывод: header('Content-Type: image/jpeg'); echo thumbnail('photo.jpg');

Результат - JPEG изображение указанного размера. Для экономии места можно кэшировать миниатюры.

Интеграция с базой данных для хранения метаданных

Пример

// При сканировании директории записывать в БД размер, дату, md5
$stmt = $pdo->prepare('INSERT INTO files (path, size, hash) VALUES (?, ?, ?)
    ON DUPLICATE KEY UPDATE size=VALUES(size), hash=VALUES(hash)');
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($root)) as $file) {
    $path = $file->getPathname();
    $size = $file->getSize();
    $hash = md5_file($path);
    $stmt->execute([$path, $size, $hash]);
}

Позволяет быстро искать дубликаты, отслеживать изменения.

RESTful API для файлового браузера

Пример

// GET /api/list?dir=subfolder
header('Content-Type: application/json');
$path = realpath($root . '/' . $_GET['dir']);
if (!$path || strpos($path, $root) !== 0) {
    http_response_code(403);
    echo json_encode(['error' => 'Forbidden']);
    exit;
}
$items = array_diff(scandir($path), ['.', '..']);
$result = [];
foreach ($items as $item) {
    $full = $path . '/' . $item;
    $result[] = [
        'name' => $item,
        'type' => is_dir($full) ? 'dir' : 'file',
        'size' => is_file($full) ? filesize($full) : null,
        'path' => substr($full, strlen($root)+1)
    ];
}
echo json_encode($result);

Ответ в JSON для клиентского приложения. Пример использования с fetch на фронтенде.

Файловый браузер на PHP - comments

En
Php file browser (php)