Skip to content

Практическая работа №13: Работа с файловой системой в PHP


Работа с файловой системой в PHP

Section titled “Работа с файловой системой в PHP”

Цель работы: Научиться работать с файлами и директориями в PHP: чтение и запись файлов, получение метаданных (размер, права), создание/удаление/копирование каталогов, рекурсивные операции, корректная обработка загрузки файлов и базовые приёмы обеспечения безопасности.

Основные теоретические положения

Section titled “Основные теоретические положения”

1. Что такое файловая система с точки зрения PHP?

Section titled “1. Что такое файловая система с точки зрения PHP?”

Файловая система — это иерархическая структура для хранения файлов и директорий на диске. PHP предоставляет набор встроенных функций для работы с файловой системой: чтение/запись, проверка существования, получение метаданных, изменение прав, работа с потоками и блокировками и т.д.

2. Ключевые функции и возможности

Section titled “2. Ключевые функции и возможности”

Ниже перечислены основные функции, которые понадобятся в работе:

  • Проверка и информация:

    • file_exists($path), is_file($path), is_dir($path)
    • filesize($path) — размер файла в байтах
    • fileperms($path) — права доступа (числовой битовый набор)
    • fileowner($path), filegroup($path) — владелец/группа (не всегда доступны на Windows)
    • realpath($path) — абсолютный путь (полезен для безопасности)
    • mime_content_type($path) / finfo_file() — определение MIME-типа
  • Чтение и запись:

    • file_get_contents($file), file_put_contents($file, $data, $flags = 0) (с флагами FILE_APPEND, LOCK_EX)
    • fopen($file, $mode), fread(), fwrite(), fclose(), feof()
    • Потоки (stream) и функции stream_get_contents, fseek, ftell
  • Работа с директориями:

    • scandir($dir), opendir(), readdir(), closedir()
    • mkdir($dir, $mode = 0777, $recursive = false), rmdir($dir) — удалить пустой каталог
    • glob($pattern) — поиск файлов по шаблону
  • Управление файлами:

    • copy($source, $dest), rename($old, $new), unlink($file) — удаление
    • touch($file, $time = null) — изменить время доступа/изменения
    • chmod($file, $mode) — изменить права доступа
    • flock($handle, LOCK_EX) — файловая блокировка
  • Безопасность:

    • Проверка и нормализация путей (realpath) — предотвращение path traversal.
    • Валидация расширений и MIME-типа при загрузке.
    • Использование basename() и белого списка допустимых имён/расширений.
    • Правильная установка прав и использование umask() при создании временных файлов/директорий.

Алгоритм выполнения работы

Section titled “Алгоритм выполнения работы”
  1. Создайте файл filesystem.php.
  2. В начале файла откройте PHP-блок <?php ... ?>.
  1. Реализуйте каждый пункт практики в отдельном блоке кода с комментариями.
  2. Для вывода результатов используйте echo/printf и аккуратно форматируйте (например — <pre> для структурированных данных).
  3. По возможности пишите небольшие пользовательские функции для повторяющихся операций (например, рекурсивный подсчёт размера каталога).
  1. В корне практики создайте тестовую директорию test_data/ с несколькими файлами и подкаталогами (код должен сам создавать тестовые файлы, если их нет).
  2. Не используйте опасные пути; все операции выполняйте в пределах test_data/.

Задания для выполнения

Section titled “Задания для выполнения”

Часть 1 — Базовые операции (стандартные функции)

Section titled “Часть 1 — Базовые операции (стандартные функции)”

Для каждого пункта напишите отдельный кодовый блок, выведите исходные данные и результат.

  1. Создайте в папке test_data/ файл hello.txt со строкой Hello, filesystem!. (Используйте file_put_contents и проверьте file_exists.)
  2. Прочитайте hello.txt и выведите содержимое на экран (file_get_contents).
  3. Узнайте размер hello.txt и выведите его.
  4. Узнайте и выведите права доступа к файлу в восьмеричном формате (пример: 0644). (Используйте fileperms + sprintf.)
  5. Создайте поддиректорию test_data/uploads/ (если её нет) с правами 0755.
  6. Скопируйте hello.txt в test_data/uploads/hello_copy.txt.
  7. Переименуйте hello_copy.txt в greeting.txt.
  8. Удалите временный файл test_data/temp.txt, если он существует.
  9. Сгенерируйте список файлов в test_data/ и выведите только имена файлов (используйте scandir или glob).
  10. Используя glob, найдите все .txt файлы в test_data/ и выведите их количество.

Часть 2 — Работа с потоками и блокировками

Section titled “Часть 2 — Работа с потоками и блокировками”
  1. Откройте test_data/log.txt в режиме a+, запишите в него строку с текущей датой и временем, гарантируя эксклюзивную блокировку (flock), затем закройте файл.
  2. Прочитайте и выведите последние 5 строк из test_data/log.txt. (Можно читать с конца — примерно: fseek и fread, либо считать весь файл и взять array_slice.)

Часть 3 — Рекурсивные операции и информация о каталоге

Section titled “Часть 3 — Рекурсивные операции и информация о каталоге”
  1. Напишите функцию dir_size($dir) — возвращает суммарный размер всех файлов в каталоге (рекурсивно).
  2. Напишите функцию delete_dir($dir) — рекурсивно удаляет каталог и всё содержимое (осторожно: test_data/ только).
  3. Напишите функцию copy_dir($src, $dst) — рекурсивно копирует содержимое каталога.
  4. Выведите количество файлов и количество поддиректорий в test_data/ (рекурсивно).

Часть 4 — Пользовательские функции (реализовать и протестировать)

Section titled “Часть 4 — Пользовательские функции (реализовать и протестировать)”
  1. safe_filename($name) — очищает имя файла от недопустимых символов, оставляет только латиницу, цифры, дефисы и подчёркивания, заменяет пробелы на _. Возвращает безопасное имя.
  2. store_json($path, $data) — сериализует массив в JSON и безопасно записывает в файл (atomic write: запись во временный файл + rename).
  3. read_csv($path): array — читает CSV-файл и возвращает массив строк (используйте fgetcsv).
  4. list_files_by_ext($dir, array $exts): array — возвращает список файлов с указанными расширениями (рекурсивно).

Часть 5 — Имитация безопасной загрузки файла (без фронтенда)

Section titled “Часть 5 — Имитация безопасной загрузки файла (без фронтенда)”

Напишите обработчик (функцию) handle_upload(array $uploadedFile, string $destDir) который:

  • Проверяет наличие ошибок загрузки (эмулируйте массив, похожий на $_FILES['file']).
  • Проверяет расширение и MIME по белому списку (['jpg','png','pdf','txt']).
  • Приводит имя к безопасному варианту safe_filename.
  • Записывает файл в uploads/ с уникальным именем (например, uniqid() + расширение).
  • Возвращает путь сохранённого файла или текст ошибки.

Важно: обработчик должен демонстрировать основные шаги безопасности (проверка MIME, ограничение размера, basename/realpath, запись только в директорию назначения).

  1. Что такое файловая система и какие функции PHP используются для проверки существования файла и директории?
  2. Чем отличается file_get_contents от использования fopen/fread?
  3. Как безопасно записать данные в файл, чтобы избежать одновременной порчи данных несколькими процессами?
  4. Что такое path traversal и как от него защититься в PHP?
  5. Как получить права доступа файла в человекочитаемом восьмеричном виде?
  6. Для чего нужна функция realpath?
  7. Почему важно валидировать MIME-типы и расширения при загрузке файлов?
  8. Что такое atomic write при записи файлов и как его реализовать?
  • Корректное использование стандартных функций чтения/записи и работы с директориями: 30%.
  • Правильная реализация рекурсивных операций (копирование, удаление, подсчёт размера): 25%.
  • Реализация безопасного хранилища/обработчика загрузки и функций безопасности (safe_filename, realpath): 20%.
  • Оформление кода, комментарии, читаемость и ответы на контрольные вопросы: 15%.
  • Дополнительные полезные функции/логгирование/тестовые наборы: 10%.

Рекомендации по оформлению кода

Section titled “Рекомендации по оформлению кода”
  • Комментируйте каждый блок: что делает функция, какие параметры и что возвращает.
  • Не выполняйте потенциально опасные операции вне test_data/ — все пути должны быть ограничены корневой тестовой директорией.
  • Используйте try/catch и проверяйте возвращаемые значения функций.
  • Если используете многобайтовые строки в именах файлов (редкие случаи), будьте аккуратны с функциями преобразования — чаще используйте латиницу в имёнах файлов.

Рекомендуемая литература

Section titled “Рекомендуемая литература”
  • php.net — Документация по файловым функциям и потокам PHP (разделы Filesystem и Streams).
  • W3Schools — Краткие примеры по работе с файлами (см. раздел PHP File Handling).
  • PHP The Right Way — Рекомендации по лучшим практикам (включая безопасность при работе с файлами).
  • Дэвид Скляр — (пример книги/учебника по PHP; для дополнительного чтения — главы о файловых операциях).