Главная » IT-записки » HTML, CSS, JS and PHP » Загрузка изображений с помощью PHP

Загрузка изображений с помощью PHP

Если вы создаете систему управления сайтом(CMS), то есть вероятность, что вам потребуется реализовать загрузку изображений на сервер. Загрузку изображений довольно просто реализовать. В этом примере мы реализуем следующее:

  • Проверка формата загружаемого файла
  • Файл имеет размер меньше, чем разрешено для загрузки(в php.ini)
  • Проверка уникальности имени файла
Создание и настройка папки для загрузки

Первое, что надо сделать это создать папку на сервере. Обычно папки на сервере настроены таким образом, что посетители не могут загружать в них файлы. Это сделано из соображений безопасности. Для того, чтобы иметь возможность загрузки изображений мы должны изменить разрешения для папки. В UNIX подобных системах это достигается установкой разрешений в режим 755.

Создание HTML формы для загрузки файлов

Нам нужно создать HTML форму для загрузки файлов на сервер. Отличие от простых форм в следующем: указан дополнительный атрибут enctype="multipart/form-data". Также нам нужен элемент типа input с атребутом type="file".

<form action="uploader.php" enctype="multipart/form-data" method="post">
<input type="file" name="myFile">
<input type="submit" value="Upload File">
</form>
Проверка формата файла

Вы создали форму, теперь надо проверить размер загружаемого файла и его расширение. Вы ведь не хотите видеть на сервере неприятные JS, EXE или PHP файлы. Главный способ для проверки загружаемого файла это использовать суперглобальный массив $_FILES. Это ассоциативный массив элементов, которые были загружены на сервер с помощью метода HTTP POST.
Если применить print_r() к $_FILES, то вы получите содержимое массива, который должен выглядет примерно так:

print_r($_FILES);
Array ( [myFile] => Array (
  [name] => view1.jpg
  [type] => image/jpeg
  [tmp_name] => /tmp/phpLh4TJG
  [error] => 0
  [size] => 23424 )
)

Значение 0 у параметра error означает отсутствие ошибок.

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

$fileError = $_FILES['filmImage']['error'];
if($fileError > 0){
    header("Location:".$returnURL."?err=imgUploadError");
    exit;
}

Мы также можем проверить размер файла изображения:

$maxSize = 100000;
$fileSize = $_FILES['filmImage']['size'];
if($fileSize > $maxSize){
      header("Location:".$returnURL."?err=tooBig");
      exit;
}

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

Во-первых, мы будем использовать значение tmp_name из суперглобального массива $_FILES, чтобы получить путь к временному файлу. Затем создаем массив с типами файлов, которые нам подходят. Проверяем файл, чтобы узнать, подходит ли его расширение для нас и если подходит, то получаем настоящее расширение и сохраняем его в переменной:

$fileTempName = $_FILES['filmImage']['tmp_name'];
$trueFileType = exif_imagetype($fileTempName);
$allowedFiles = array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG);
if (in_array($trueFileType, $allowedFiles)) {
    switch($trueFileType){
    case 1 : $fileExt  = ".gif";
    break;
    case 2: $fileExt  = ".jpg";
    break;
    case 3 : $fileExt  = ".png";
    break;
     }
}else{
    header("Location:".$returnURL."?err=WrongFileType");
    exit;
}
Переименовываем файл

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

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

$stmt = $mysqli->prepare("INSERT INTO movies(filmName, filmDescription, filmPrice, filmReview) VALUES (?, ?, ?, ?)");
$stmt->bind_param('ssdi', $filmName, $filmDescription, $filmPrice, $filmReview);
$stmt->execute();
$newID = $stmt->insert_id;
$newFileName = $newID . $fileExt;
$stmt->close();

Этот код добавляет новую запись в таблицу movies, и я использую insert_id для получения значения первичного ключа новой записи. Мы уже знаем расширение файла и просто добавляем его к полученному значению. Пример нового имени файла: 32423.jpg

Перемещение временного файла

Теперь мы знаем имя файла и нам надо переместить его из временной папки. Этот код использует суперглобальный массив $_SERVER, чтобы получить путь к текущему каталогу. Папка uploadedImages находится тамже где и PHP файл, выполняющий загрузку.

// Получаем путь к папке
$myPathInfo = pathinfo($_SERVER['DOCUMENT_ROOT'].$_SERVER['PHP_SELF']);
$currentDir = $myPathInfo['dirname'];
$imgDir = $currentDir . '/uploadedImages/';

Последний шаг состоит в перемещении временного файла в папку uploadedImages. Для этого я буду использовать PHP метод move_uploaded_file().

$newImgLocation = $imgDir . $newFileName;
if(move_uploaded_file($fileTempName, $newImgLocation)){
    header("Location:".$returnURL);
}else{
    header("Location:".$returnURL."?err=UploadProb");
}
Memory: 4 mb, MySQL: 0.0018 s, 0 request(s), PHP: 0.0252 s, total: 0.0270 s, document retrieved from cache.