Завантаження зображень на сервер і зміна розміру зображення на PHP

33

Сьогодні я хочу розповісти про реалізацію досить популярною завдання. По-перше, це завантаження зображень на сервер. А по-друге, це зміна розміру зображення. Також розглянемо поворот і зміна якості.

Завантажити вихідний код собі на комп’ютер!

Трохи теорії завантаження зображень на сервер засобами PHP

Ви не можете відразу завантажити файл у власну папку. Спочатку він завантажується в тимчасову директорію сервера, а потім обробляється за допомогою PHP интерпритатора. По закінченню сесії тимчасовий файл автоматично видаляється. Тобто, ми спочатку закидаємо файл у тимчасову папку, а потім перекладаємо в потрібну.

$_FILES це масив завантажених файлів. Він має параметри (на прикладі файлу picture):

$_FILES[‘ picture ‘][‘name’] – справжнє ім’я файлу. Наприклад: image.jpg.

$_FILES[‘ picture ‘][‘size’] – розмір файлу в байтах.

$_FILES[‘ picture ‘][‘type’] – MIME-тип завантаженого файлу. Наприклад: image/gif, image/png image/jpeg.

$_FILES[‘ picture ‘][‘tmp_name’] – містить ім’я файлу в тимчасовому каталозі, наприклад: /tmp/phpV3b3qY. Саме цей параметр використовується для переміщення файлів після завантаження.

$_FILES[‘ picture ‘][‘error’] – код помилки.

Підготовка

Для початку нам потрібна форма для завантаження. Візьмемо найпростішу форму.

Параметр enctype=»multipart/form-data» обов’язковий для такої форми. Тег відповідає за поле для введення імені файлу, який завантажується на сервер.

Також нам потрібно обробник події – завантаження файлу. Спочатку у нас буде одна настройка – шлях збереження зображення. Можна вказувати як прямий, так і відносний шлях. У разі POST запиту обробник спробує здійснити завантаження файлу по вказаному шляху. Скрипт повідомить про результат завантаження – вдала вона чи ні.

Функція copy, як ви напевно здогадалися, відповідає за копіювання файлів з одного місце в інше. Ми копіюємо файл з тимчасової папки сервера в потрібну, зберігши ім’я файлу.

Домовимося, що і форма та її обробник будуть знаходитися в одному файлі upload.php.

Разом маємо простий, але робочий скрипт. Його можна закинути на хостинг, створити папку i і потренуватися з завантаженням файлів.

Завантаження зображення з зміною розмірів

Завантаження зображення з зміною розмірів

свойства изображения

Перевірки

Будь-яка форма представляє для сайту небезпека. І особливо форма завантаження файлів. Зловмисник може завантажити скрипт і виконати його на сервері. Тому необхідно потурбуватися безпекою.

Найпростіші і обов’язкові перевірки – на розмір і тип файлу. Для цього вкажемо типи і розмір.

Тип файлу зазначимо у вигляді масиву:

$types = array(‘image/gif’, ‘image/png’, ‘image/jpeg’);

розмір файлу у байтах:

$size = 1024000;

Перевіряємо тип файлу. У разі неприпустимого типу припиняємо роботу скрипта і виводимо відповідне повідомлення. Функція in_array перевіряє присутність значення в масиві.

// Перевіряємо тип файлу
if (!in_array($_FILES[‘picture’][‘type’], $types))
die(‘Заборонений тип файлу. Спробувати інший файл?’);

свойства изображения

Перевіряємо розмір файлу. У разі неправильного розміру припиняємо роботу скрипта і виводимо відповідне повідомлення.

// Перевіряємо розмір файлу
if ($_FILES[‘picture’][‘size’] > $size)
die(‘завеликий розмір файлу. Спробувати інший файл?’);

свойства изображения

Разом отримуємо такий скрипт. Скрипт робочий, можна балуватися. Трохи забігаючи наперед, додамо також параметр $tmp_path – шлях до папки тимчасових файлів.

$size)
die(‘завеликий розмір файлу. Спробувати інший файл?’);
// Завантаження файлу і вивід повідомлення
if ([email protected]($_FILES[‘picture’][‘tmp_name’], $path . $_FILES[‘picture’][‘name’]))
echo ‘щось пішло не так’;
else
echo ‘Завантаження вдала Подивитися’ ;
}
?>
Завантаження зображення з зміною розмірів

Завантаження зображення з зміною розмірів

Зміна розмірів зображень PHP

Приступимо до найцікавішого, а саме зміни розмірів зображення за допомогою PHP. Для цього напишемо функцію resize. Зробимо також можливим змінювати якість зображення і повертати його.

Розмір зображення будемо підставляти виходячи з параметра. Це буде або ескіз ($type = 1), або велике зображення ($type = 2).

Отже, шапка функції у нас вийшла така:

function resize($file, $type = 1, $rotate = null, $quality = null)

За замовчуванням підставляємо розміри ескізу, а поворот і якість за замовчуванням не використовуються. Підемо далі.

Встановлюємо обмеження розміру зображення по ширині. Функцію можна зробити більш абстрактною, якщо ставити ці значення в параметрах, а також зробити можливим обмеження і по висоті. Проте в даному випадку нам не потрібна така універсальність.

$max_thumb_size = 200;
$max_size = 800;

Встановлюємо якість зображення за замовчуванням (за $quality = null) рівним 75%.

if ($quality == null)
$quality = 75;

Далі створюємо зображення для подальших перетворень. Для створення використовуємо функцію в залежності від типу файлу (jpg, png або gif). Функції створення називаються дуже лаконічно imagecreatefrom + тип файлу.

if ($file[‘type’] == ‘image/jpeg’)
$source = imagecreatefromjpeg ($file[‘tmp_name’]);
elseif ($file[‘type’] == ‘image/png’)
$source = imagecreatefrompng ($file[‘tmp_name’]);
elseif ($file[‘type’] == ‘image/gif’)
$source = imagecreatefromgif ($file[‘tmp_name’]);
else
return false;

Якщо вказано параметр $rotate, виконуємо поворот зображення. Робимо це за допомогою функції rotate(), параметрами якої є: зображення, градуси, фон зображення для зафарбовування порожніх областей, утворених при повороті. Для того щоб порожні області не виникали, повертаємо зображення на кут в 90, 180, 270 градусів.

if ($rotate != null)
$src = imagerotate($source, $rotate, 0);

Далі визначаємо висоту і ширину зображення з допомогою функцій imagesx і imagesy.

$w_src = imagesx($src);
$h_src = imagesy($src);

Залежно від типу (ескіз або велике зображення) встановлюємо обмеження по ширині.

if ($type == 1)
$w = $max_thumb_size;
elseif ($type == 2)
$w = $max_size;

Далі, якщо ширина зображення більше максимальної, проводимо перетворення. Інакше просто зберігаємо зображення і очищаємо пам’ять. Зберігаємо зображення за допомогою функції imagejpeg. В даному прикладі, розглянуто збереження тільки у форматі jpg, проте функціонал завжди можна розширити. Видаляємо зображення з пам’яті за допомогою функції imagedestroy.

В якості результату роботи функції повертаємо ім’я файлу. Воно нам ще знадобиться.

if ($w_src > $w)
{
// перетворення
}
else
{
imagejpeg($src, $tmp_path . $file[‘name’], $quality);
imagedestroy($src);
return $file[‘name’];
}

Повернемося до перетворення. Спочатку обчислюємо пропорції і розміри перетвореного зображення.

$ratio = $w_src/$w;
$w_dest = round($w_src/$ratio);
$h_dest = round($h_src/$ratio);

Далі створюємо порожню картинку (функція imagecreatetruecolor) з висотою та шириною, отриманими на попередньому кроці.

$dest = imagecreatetruecolor($w_dest, $h_dest);

І копіюємо вихідне зображення ($src) у тільки що створене ($dest), змінюючи його розміри. Функція imagecopyresampled робить це з пересэмплированием, що покращує якість.

imagecopyresampled($dest, $src, 0, 0, 0, 0, $w_dest, $h_dest, $w_src, $h_src);

І нарешті, зберігаємо отримане зображення і очищаємо пам’ять.

imagejpeg($src, $tmp_path . $file[‘name’], $quality);
imagedestroy($dest);
imagedestroy($src);

Отже, функція отримує початкове зображення і параметри перетворення, виконує перетворення, зберігає отриманий файл у тимчасову папку і повертає ім’я зображення. Тепер нам залишилося тільки перекласти файл у папку.

Відповім заздалегідь на питання «Чому ми не можемо відразу покласти файл у папку?». Можемо. Однак не робимо для збільшення глибини абстракції, тобто, щоб надати певну універсальність функції. Ви ж зможете її використовувати на різних сайтах.

Зовсім забув. Додаємо в початок функції рядок:

global $tmp_path;

Вона означає, що функції буде використана глобальна змінна $tmp_path – шлях до тимчасової папки.

Виклик функції

Функцію потрібно викликати відразу після перевірок. А також слід змінити ту частину скрипта, де ми копіюємо зображення в папку. Адже ви тепер працюємо з новим зображенням. Тепер схема завантаження така: комп’ютер → тимчасова папка сервера → наша тимчасова папка → кінцева папка. Тобто, додався ще один проміжний пункт.

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

У такому разі виклик функції буде такою:

$name = resize($_FILES[‘picture’], $_POST[‘file_type’], $_POST[‘file_rotate’]);

Кінцевий результат

І нарешті, кінцевий результат.

Завантаження зображення з зміною розмірів

Завантаження зображення з зміною розмірів

Заборонений тип файлу. Спробувати інший файл?

‘);
// Перевіряємо розмір файлу
if ($_FILES[‘picture’][‘size’] > $size)
die(‘

Завеликий розмір файлу. Спробувати інший файл?

‘);
// Функція зміни розміру
// Змінює розмір зображення в залежності від type:
// type = 1 — ескіз
// type = 2 — велике зображення
// rotate — поворот на кількість градусів (бажано використовувати значення 90, 180, 270)
// quality — якість зображення (за замовчуванням 75%)
function resize($file, $type = 1, $rotate = null, $quality = null)
{
global $tmp_path;
// Обмеження по ширині в пікселях
$max_thumb_size = 200;
$max_size = 600;
// Якість зображення за замовчуванням
if ($quality == null)
$quality = 75;
// Створюємо початкове зображення на основі вихідного файлу
if ($file[‘type’] == ‘image/jpeg’)
$source = imagecreatefromjpeg($file[‘tmp_name’]);
elseif ($file[‘type’] == ‘image/png’)
$source = imagecreatefrompng($file[‘tmp_name’]);
elseif ($file[‘type’] == ‘image/gif’)
$source = imagecreatefromgif($file[‘tmp_name’]);
else
return false;
// Повертаємо зображення
if ($rotate != null)
$src = imagerotate($source, $rotate, 0);
else
$src = $source;
// Визначаємо ширину і висоту зображення
$w_src = imagesx($src);
$h_src = imagesy($src);
// В залежності від типу (ескіз або велике зображення) встановлюємо обмеження по ширині.
if ($type == 1)
$w = $max_thumb_size;
elseif ($type == 2)
$w = $max_size;
// Якщо ширина більше заданої
if ($w_src > $w)
{
// Обчислення пропорцій
$ratio = $w_src/$w;
$w_dest = round($w_src/$ratio);
$h_dest = round($h_src/$ratio);
// Створюємо порожню картинку
$dest = imagecreatetruecolor($w_dest, $h_dest);
// Копіюємо старе зображення в нове зі зміною параметрів
imagecopyresampled($dest, $src, 0, 0, 0, 0, $w_dest, $h_dest, $w_src, $h_src);
// Висновок картинки і очищення пам’яті
imagejpeg($dest, $tmp_path . $file[‘name’], $quality);
imagedestroy($dest);
imagedestroy($src);
return $file[‘name’];
}
else
{
// Висновок картинки і очищення пам’яті
imagejpeg($src, $tmp_path . $file[‘name’], $quality);
imagedestroy($src);
return $file[‘name’];
}
}
$name = resize($_FILES[‘picture’], $_POST[‘file_type’], $_POST[‘file_rotate’]);
// Завантаження файлу і вивід повідомлення
if ([email protected]($tmp_path . $name, $path . $name))
echo ‘

Щось пішло не так.

‘;
else
echo ‘

Завантаження пройшла вдало Подивитися.

‘;
// Видаляємо тимчасовий файл
unlink($tmp_path . $name);
}
?>

Тип завантаження

Ескіз
Велике зображення

Поворот

свойства изображения

Післямова

Природно, розглянутий приклад навчальний. Однак він цілком робочий. Що ви можете спробувати, закинувши скрипт на сервер і створивши папки для зображень і тимчасових файлів. Скрипт можна нескінченно допрацьовувати, змінювати рівень абстракції, додавати умови і параметри перетворення, перевірки, накладати «водяний знак».

Ідеальний варіант – осмислити і допилити до своїх вимог.

Домашнє завдання

Звичайно, завдання перевіряти ніхто не буде. Однак я рекомендую його виконати для себе. Адже програмування – це, насамперед, практика. Отже:

Винесіть розміри ескізу ($max_thumb_size) і великого зображення ($max_size) функції в налаштування файлу.

Спробуйте їх у параметрах функції. Це значно підвищить рівень абстракції.

Опрацюйте варіант, коли зображення обмежується по більшій стороні, а не тільки по ширині.

Спробуйте отримати на виході файл того ж типу, що й вихідний. Тобто, наприклад, якщо ви завантажуєте gif, то і зменшена копія буде gif.

Спробуйте генерувати і ескіз і великий файл за одне завантаження.

Спробуйте накласти «водяний знак».

Використовуючи бонусний код, додайте в функцію можливість створення квадратних файлів. Додайте у форму вибір типу обрізки – квадратна чи пропорційна.

Удачі в розробках!

P. S. Якщо ви захочете генерувати не пропорційне зображення, а вирізати серединку і робити квадратну картинку, вам допоможе цей код. Вставити його в функцію resize ви повинні самі. Впевнений, що у вас вийде.

// Створюємо пустий квадратну картинку
$dest = imagecreatetruecolor($w $w);
// Вирізаємо квадратну серединку по x, якщо фото горизонтальне
if ($w_src > $h_src)
imagecopyresampled($dest, $src, 0, 0, round((max($w_src, $h_src) — min($w_src, $h_src))/2), 0, $w $w, min($w_src, $h_src), min($w_src, $h_src));
// Вирізаємо квадратну серединку по y, якщо фото горизонтальне
elseif ($w_src < $h_src)
imagecopyresampled($dest, $src, 0, 0, 0, round((max($w_src, $h_src) — min($w_src, $h_src))/2), $w $w, min($w_src, $h_src), min($w_src, $h_src));
// Квадратна картинка масштабується без вирізок
elseif ($w_src == $h_src)
imagecopyresampled($dest, $src, 0, 0, 0, 0, $w, $w $w_src, $w_src);

До наступних зустрічей, шановні читачі

Якщо у вас є питання, щодо завантаження зображень на сервер і зміни розмірів зображень засобами мови PHP, то пишіть в комменатриях до статті, я обов’язково відповім!

E-mail: [email protected]

Проект webformyself.com — Як створити свій сайт. Основи самостійного сайтобудування

«Кіберсант-вебмастер» — самий повний курс по сайтостроению в рунеті!

P. S. Хочете опублікувати цікавий тематичний матеріал і заробити? Якщо відповідь «Так», то тисніть сюди.