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

Digital-студия WNDER

Чтение и запись файлов: базовые операции

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

Самая простая — file_get_contents(). Она читает весь файл в строку. Это как открыть книгу и прочитать её за один присест.


$content = file_get_contents('settings.txt');
echo $content;

А для записи используем file_put_contents(). Она записывает строку в файл. Если файла нет — создаст его. Удобно, правда?


$newContent = 'version=2.0';
file_put_contents('settings.txt', $newContent);

Но что если файл большой, например, лог на 100 МБ? Читать его целиком — плохая идея, память лопнет. Тут на помощь приходят fopen(), fgets() и fclose(). Они работают как поток — читают по строчке, не нагружая сервер.


$handle = fopen('big_log.txt', 'r'); // 'r' — режим чтения
if ($handle) {
    while (($line = fgets($handle)) !== false) {
        echo $line;
    }
    fclose($handle);
}
Правило: Если файл меньше 1 МБ — смело используй file_get_contents(). Если больше — бери fopen() и читай порциями. Так ты сэкономишь память и ускоришь скрипт.

Загрузка файлов на сервер: без паники

Загрузка файлов — это классика. Пользователь выбирает файл в форме, нажимает кнопку, и файл летит на сервер. В PHP это делается через суперглобальный массив $_FILES. Давай разберём на примере.

Сначала HTML-форма. Обрати внимание на атрибут enctype="multipart/form-data" — без него ничего не заработает.


Теперь PHP-обработчик. Проверяем, загрузился ли файл, и перемещаем его в нужную папку.


if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (isset($_FILES['userfile']) && $_FILES['userfile']['error'] === UPLOAD_ERR_OK) {
        $uploadDir = 'uploads/';
        $uploadFile = $uploadDir . basename($_FILES['userfile']['name']);
        
        if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadFile)) {
            echo 'Файл успешно загружен!';
        } else {
            echo 'Ошибка при перемещении файла.';
        }
    } else {
        echo 'Файл не загружен. Код ошибки: ' . $_FILES['userfile']['error'];
    }
}

Что важно знать про $_FILES? Это массив, где для каждого файла хранятся такие данные:

Ключ Описание
name Оригинальное имя файла на компьютере пользователя
type MIME-тип файла (например, image/jpeg)
tmp_name Временный путь, куда PHP сохранил файл
error Код ошибки (0 — всё ок, 1 — превышен размер и т.д.)
size Размер файла в байтах

Никогда не доверяй имени файла от пользователя. Всегда переименовывай его, например, с помощью uniqid(), чтобы избежать конфликтов и атак.

Работа с изображениями: ресайз, кроп и водяные знаки

Изображения — это отдельная песня. PHP умеет с ними работать через библиотеку GD. Она встроена в большинство сборок PHP, так что ничего дополнительно ставить не нужно.

Сначала создадим изображение из файла. Допустим, у нас есть картинка photo.jpg. Загрузим её и получим размеры.


$image = imagecreatefromjpeg('photo.jpg');
$width = imagesx($image);
$height = imagesy($image);
echo "Размер: {$width}x{$height}";

Теперь уменьшим её до 300 пикселей по ширине, сохраняя пропорции. Для этого создадим новое пустое изображение и скопируем туда старое с изменением размера.


$newWidth = 300;
$newHeight = intval($height * ($newWidth / $width));

$newImage = imagecreatetruecolor($newWidth, $newHeight);
imagecopyresampled($newImage, $image, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);

imagejpeg($newImage, 'photo_small.jpg', 90); // качество 90%
imagedestroy($image);
imagedestroy($newImage);

Кстати, если нужно обрезать картинку (кроп), то меняем координаты в imagecopyresampled(). Например, вырезаем центральный квадрат.


$size = min($width, $height); // сторона квадрата
$srcX = intval(($width - $size) / 2); // сдвиг по X
$srcY = intval(($height - $size) / 2); // сдвиг по Y

$cropped = imagecreatetruecolor($size, $size);
imagecopyresampled($cropped, $image, 0, 0, $srcX, $srcY, $size, $size, $size, $size);
imagejpeg($cropped, 'photo_cropped.jpg', 90);

Ещё одна частая задача — добавить водяной знак. Для этого создадим изображение из PNG с логотипом и наложим его на основное.


$watermark = imagecreatefrompng('logo.png');
$wmWidth = imagesx($watermark);
$wmHeight = imagesy($watermark);

// Позиция: правый нижний угол с отступом 10px
$destX = $width - $wmWidth - 10;
$destY = $height - $wmHeight - 10;

imagecopy($image, $watermark, $destX, $destY, 0, 0, $wmWidth, $wmHeight);
imagejpeg($image, 'photo_with_watermark.jpg', 90);
Лайфхак: Для прозрачности у водяного знака используй PNG с альфа-каналом. И не забудь вызвать imagealphablending($image, true) перед копированием, иначе фон будет чёрным.

Безопасность: как не подхватить вирус

Работа с файлами — это как открывать дверь незнакомцу. Нужно быть осторожным. Вот основные правила безопасности.

  • Проверяй MIME-тип и расширение файла. Не доверяй только одному — лучше оба.
  • Ограничивай размер файла. В PHP это делается через настройку upload_max_filesize в php.ini или через проверку $_FILES['userfile']['size'].
  • Переименовывай файлы при сохранении. Никогда не используй оригинальное имя.
  • Для изображений проверяй, что файл действительно изображение, через getimagesize().

$info = getimagesize($_FILES['userfile']['tmp_name']);
if ($info === false) {
    die('Это не изображение!');
}

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

Оптимизация: ускоряем загрузку страниц

Большие изображения — враг скорости. Даже если ты сделал ресайз, файл может весить прилично. Используй сжатие и правильный формат.

Формат Когда использовать Сжатие
JPEG Фотографии, сложные изображения Потеря качества, но маленький размер
PNG Логотипы, скриншоты, прозрачность Без потерь, но файлы больше
WebP Современный формат, хорош для всего Лучшее сжатие, но не везде поддерживается

В PHP можно конвертировать в WebP с помощью imagewebp(). Например, после ресайза:


imagewebp($newImage, 'photo.webp', 80); // качество 80%

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

Итоги: что мы узнали

Работа с файлами и изображениями в PHP — это не ракетостроение. Главное — знать основные функции и не забывать о безопасности. Мы разобрали, как читать и записывать файлы, загружать их на сервер, обрабатывать изображения и защищаться от атак.

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

Если нужна помощь с более сложными задачами — загляни в Digital-студию WNDER, там профессионалы своего дела.

Студия WNDER