Создание файлового менеджера на PHP: от простого скрипта до фреймворка

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

Файловый менеджер на PHP: принципы и реализация

Базовый самописный файловый менеджер

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

Пример простейшего менеджера, выводящего содержимое текущей директории:


<?php
$dir = __DIR__;
$items = scandir($dir);
echo "<ul>";
foreach ($items as $item) {
    if ($item != '.' && $item != '..') {
        echo "<li>" . htmlspecialchars($item) . "</li>";
    }
}
echo "</ul>";
?>

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

Данный код выводит список файлов и папок в корне скрипта. Для навигации по папкам необходимо добавить параметр dir в URL и обрабатывать его с проверкой на выход за пределы разрешённой директории.

Типичная ошибка:

Попытка использовать $_GET['dir'] без валидации ведёт к Path Traversal атаке. Решение - проверять, что конечный путь начинается с разрешённой корневой директории, и удалять подстроки .. при помощи realpath().

Пошаговая реализация операций:

  • Создание папки: mkdir($_GET['newfolder'], 0775); с проверкой прав.
  • Загрузка файла: форма с enctype="multipart/form-data", сохранение через move_uploaded_file. Убедиться, что тип файла разрешён.
  • Удаление: unlink($filepath) для файлов, rmdir($dirpath) для пустых папок. Для непустых папок требуется рекурсивное удаление.
  • Переименование: rename($old, $new); с проверкой на существование нового имени.

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

Как применить готовый файловый менеджер Tiny File Manager?

Если требуется быстрое внедрение без написания собственного кода, популярным вариантом является Tiny File Manager - одностраничное веб-приложение с поддержкой AJAX, изображений, файловых операций и мультиязычности.


// Пример структуры для установки
- tinyfilemanager.php   // главный скрипт
- translations/        // файлы переводов
- config.php           // настройки (опционально)

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

Установка: скачать скрипт, поместить на сервер, изменить пароль в конфигурации. Открыть в браузере - менеджер готов к работе.

Проблема:

По умолчанию Tiny File Manager имеет один логин/пароль, что неудобно для нескольких администраторов. Решение - настроить аутентификацию через сессии или OAuth.

Ещё одна распространённая ошибка: если скрипт не показывает файлы, возможно, не установлены необходимые PHP расширения (например, mbstring, zip).

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

AJAX улучшает пользовательский опыт. Реализация на базе jQuery и PHP позволяет загружать список файлов, удалять и создавать папки асинхронно.


// JavaScript (фрагмент)
$('#loadFolder').on('click', function() {
    $.get('ajax.php', { action: 'list', dir: currentDir }, function(data) {
        $('#fileList').html(data);
    });
});

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


// PHP (ajax.php)
$dir = realpath($_GET['dir']) ?: '.';
$items = scandir($dir);
$output = '<ul>';
foreach ($items as $item) {
    if ($item[0] != '.') {
        $output .= '<li data-path="' . $dir . '/' . $item . '">' . htmlspecialchars($item) . '</li>';
    }
}
$output .= '</ul>';
echo $output;

При таком подходе нужно корректно обрабатывать запросы (действие list, delete, rename) и возвращать JSON или HTML.

Типичная ошибка:

При большом количестве файлов AJAX-запросы могут выполняться долго. Решение - использовать пагинацию на сервере и ленивую загрузку.

Ещё одна проблема: обновление списка после действий требует повторного запроса, что можно решить возвратом нового HTML после каждой операции.

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

Безопасность - критический аспект. Основные меры:

  • Ограничить корневую директорию, за пределами которой нельзя перемещаться (chroot).
  • Проверять расширения загружаемых файлов (нельзя загружать .php, .phtml и т.д., если нет необходимости).
  • Использовать токены CSRF для всех операций.
  • Требовать аутентификацию и сессии.

// Проверка пути на основе белого списка
$allowedBase = realpath(__DIR__ . '/files');
$userPath = realpath($_GET['dir']);
if (strpos($userPath, $allowedBase) !== 0) {
    die('Недопустимый путь');
}

Это предотвращает выход за пределы разрешённой папки.

Распространённая ошибка:

Использование basename() без realpath() не защищает от атак вида ../../../etc/passwd. Всегда нормализуйте путь.

Ещё частая проблема - загрузка исполняемых скриптов. Решить можно как проверкой расширения, так и хранением загруженных файлов вне DocumentRoot.

Как встроить файловый менеджер в Laravel (или другой фреймворк)?

Для Laravel популярен пакет Laravel Filemanager (unisharp/laravel-filemanager), который предоставляет веб-интерфейс для управления файлами и интеграцию с редакторами (TinyMCE, CKEditor).


// Установка
composer require unisharp/laravel-filemanager
// Публикация конфигурации
php artisan vendor:publish --tag=lfm_config
// Маршруты (в routes/web.php)
Route::group(['middleware' => ['web', 'auth']], function () {
    \UniSharp\LaravelFilemanager\Lfm::routes();
});

После этого файловый менеджер доступен по адресу /laravel-filemanager. Настройка разрешённых расширений, размера и количества файлов производится в конфигурационном файле config/lfm.php.

Типичная проблема:

Конфликт с другими маршрутами - убедитесь, что middleware и префиксы не пересекаются. Также возможна ошибка 403, если не настроены права доступа к папке storage/app/public.

Решение: создать символическую ссылку php artisan storage:link и выставить права 775 на директорию хранения.

Каждый из вариантов применим в зависимости от проекта - от небольшого скрипта до крупного портала на фреймворке. Выбор зависит от требований к скорости разработки, безопасности и гибкости.

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

1. Полный пример самописного файлового менеджера с поддержкой навигации, загрузки и удаления

Ниже представлен скрипт, который показывает содержимое папки, позволяет переходить между папками, загружать файлы, удалять их и создавать новые папки. Все операции защищены минимальной проверкой.

Пример

<?php
session_start();
// Корневая разрешённая директория
$root = realpath(__DIR__ . '/user_files');
// Текущая директория (из GET или корень)
$current = isset($_GET['dir']) ? realpath($_GET['dir']) : $root;
if (strpos($current, $root) !== 0) {
    die('Доступ запрещён');
}
// Создание папки
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['newfolder'])) {
    $newFolder = $current . '/' . basename($_POST['newfolder']);
    if (!file_exists($newFolder)) {
        mkdir($newFolder, 0775, true);
    }
    header('Location: ?dir=' . urlencode($current));
    exit;
}
// Удаление
if (isset($_GET['delete'])) {
    $target = $current . '/' . basename($_GET['delete']);
    if (is_file($target)) {
        unlink($target);
    } elseif (is_dir($target)) {
        array_map('unlink', glob($target . '/*')); // удаляем файлы внутри
        rmdir($target);
    }
    header('Location: ?dir=' . urlencode($current));
    exit;
}
// Загрузка
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) {
    $uploadPath = $current . '/' . basename($_FILES['file']['name']);
    move_uploaded_file($_FILES['file']['tmp_name'], $uploadPath);
    header('Location: ?dir=' . urlencode($current));
    exit;
}
?>
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>Файловый менеджер</title></head>
<body>
<h2>Файлы в <?= htmlspecialchars(str_replace($root, '', $current) ?: '/') ?></h2>
<ul>
<?php if ($current != $root): ?>
    <li><a href="?dir=<?= urlencode(dirname($current)) ?>">(..) Наверх</a></li>
<?php endif;
foreach (scandir($current) as $item): 
    if ($item[0] == '.') continue; ?>
    <li>
        <?php if (is_dir($current . '/' . $item)): ?>
            <a href="?dir=<?= urlencode($current . '/' . $item) ?>"><?= htmlspecialchars($item) ?>/</a>
        <?php else: ?>
            <?= htmlspecialchars($item) ?>
        <?php endif; ?>
        [<a href="?dir=<?= urlencode($current) ?>&delete=<?= urlencode($item) ?>" onclick="return confirm('Удалить?')">X</a>]
    </li>
<?php endforeach; ?>
</ul>
<h3>Создать папку</h3>
<form method="post">
    <input type="text" name="newfolder" placeholder="Имя папки" required>
    <button type="submit">Создать</button>
</form>
<h3>Загрузить файл</h3>
<form method="post" enctype="multipart/form-data">
    <input type="file" name="file" required>
    <button type="submit">Загрузить</button>
</form>
</body>
</html>

Результат работы (пример вывода):

Файлы в /images/
- (..) Наверх
- photo2024.jpg  [X]
- logo.png       [X]
- diagrams/      [X]

В этом примере реализованы базовые операции, но нет проверки типов файлов при загрузке и нет защиты CSRF. Для продакшена требуется дополнить.

2. Пример настройки Tiny File Manager с кастомной аутентификацией

Вместо встроенного пароля можно подключить сессию пользователя сайта. В файле config.php (или прямо в tinyfilemanager.php) изменить проверку:

Пример

// Вместо проверки пароля
if (!isset($_SESSION['user'])) {
    header('Location: /login.php');
    exit;
}
// Установка корневой директории в зависимости от пользователя
$root_path = 'files/' . $_SESSION['user_id']; // каждый пользователь в своей папке
if (!is_dir($root_path)) mkdir($root_path, 0775, true);

Это позволит интегрировать менеджер в уже существующую систему авторизации.

3. AJAX-загрузка папок (фрагмент)

Для асинхронной загрузки содержимого папки при клике на неё можно использовать следующий код jQuery и PHP:

Пример

// JS
$('.folder').on('click', function(e) {
    e.preventDefault();
    var path = $(this).data('path');
    $.get('ajax_list.php', { dir: path }, function(html) {
        $('#files-container').html(html);
    });
});
Пример

// PHP (ajax_list.php)
$root = realpath(__DIR__ . '/files');
$dir = isset($_GET['dir']) ? realpath($_GET['dir']) : $root;
if (strpos($dir, $root) !== 0) die('Ошибка');
$items = array_diff(scandir($dir), ['.', '..']);
$output = '<ul class="file-list">';
foreach ($items as $item) {
    $fullPath = $dir . '/' . $item;
    $isDir = is_dir($fullPath);
    $output .= '<li class="' . ($isDir ? 'folder' : 'file') . '" data-path="' . htmlspecialchars($fullPath) . '">';
    $output .= ($isDir ? '<a href="#">' . htmlspecialchars($item) . '/</a>' : htmlspecialchars($item));
    $output .= '</li>';
}
$output .= '</ul>';
echo $output;

Результат - динамическая навигация без перезагрузки страницы.

4. Пример использования файлового менеджера в Laravel для выбора файла

Если требуется встроить диалог выбора файла (например, для TinyMCE), маршруты и настройки уже созданы после установки пакета. Пример вызова в шаблоне:

Пример

// В Blade-шаблоне
<textarea id="my-editor"></textarea>
<script>
tinymce.init({
    selector: '#my-editor',
    file_picker_callback: function(callback, value, meta) {
        var x = window.innerWidth / 2;
        var y = window.innerHeight / 2;
        var url = '/laravel-filemanager?type=' + meta.filetype;
        tinymce.activeEditor.windowManager.openUrl({
            title: 'Файловый менеджер',
            url: url,
            width: x,
            height: y,
            onMessage: function(dialogApi, details) {
                callback(details.content);
                dialogApi.close();
            }
        });
    }
});
</script>

После выбора файла в менеджере он вставляется в редактор.

Файловый менеджер на PHP - comments

En
Php file manager (php)