Чат PHP-разработчиков
Как загрузить файл на сервер в PHP

Загрузка файлов на сервер

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

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

Давайте для начала напишем саму форму для загрузки файла. Она ничем не отличается от обычной формы для POST-запроса. Единственное отличие – появляется input со специальным типом file. У него также как и у текстового input'а есть атрибут name. Простейшая форма для загрузки файла будет выглядеть следующим образом. Содержимое файла upload.php:

Код доступен только после покупки курса PHP для начинающих.

Для того, чтобы начать работать с файлом на стороне PHP, нужно познакомиться с ещё одним суперглобальным массивом в PHP - $_FILES. Так как мы указали в input атрибуту name значение attachment, то и узнать информацию о загружаемом нами файле можно получить по соответствующему ключу - $_FILES['attachment'].

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

Код доступен только после покупки курса PHP для начинающих.

Откроем в браузере нашу форму http://myproject.loc/upload.php, и выберем какой-нибудь файл для загрузки. Я для этого выбрал картинку, валяющуюся на рабочем столе.
выбор файла для загрузки

После нажатия на кнопку «Отправить» мы получим содержимое массива $_FILES.
Суперглобальный массив $_FILES

Значение $_FILES['attachment'] представляет собой массив с пятью ключами. Давайте рассмотрим каждый из элементов этого массива более подробно.

  • name – имя файла, переданное из браузера;
  • type – тип файла, в моём случае это image/png;
  • tmp_name – путь до временного файла, который загрузился на сервер, но если с ним до конца запроса ничего не сделать, то он удалится;
  • error – код ошибки при загрузке файла, если 0 – то ошибки нет. Изучите возможные коды ошибок вот тут;
  • size – размер загруженного файла в байтах.

Как мы уже сказали, пока что на сервере создан временный файл. Чтобы его сохранить нужно вызвать специальную функцию, которая переместит его из временной папки в нужную нам папку (в нашем случае это папка uploads). Эта функция - move_uploaded_file(). Первым аргументом она принимает путь до временного файла (в нашем случае - $_FILES['attachment']['tmp_name']), а вторым аргументом – путь, по которому нужно его сохранить. Функция вернёт true, если всё ок, и false, если что-то пошло не так.

ВНИМАНИЕ! Для перемещения временного файла в нужную вам папку стоит всегда использовать функцию move_uploaded_file(). Она предварительно проверяет, что указанный файл действительно является временным загруженным файлом, а не чем-то ещё. Другие функции для копирования файлов не подойдут, так как они эту проверку не выполняют, а это небезопасно. Кому интересно – можете подробнее прочитать тут.

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

Код доступен только после покупки курса PHP для начинающих.

Если сейчас выбрать файл и нажать на кнопку “Отправить”, то скрипт вернёт нам адрес загруженного файла.
Результат загрузки файла через PHP

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

Этот скрипт ещё очень сырой, давайте его доработаем.

Проверка на существующий файл с таким же именем

Первое, что приходит на ум – убедиться, что файл с таким именем не загружался ранее. Иначе мы рискуем перезатереть что-нибудь важное. Давайте проверим существование такого файла с помощью функции file_exists().

Код доступен только после покупки курса PHP для начинающих.

Обработка ошибок при загрузке файлов

Теперь вспомним об элементе массива по ключу error. Как мы помним, при отсутствии ошибок там будет 0. Во всех остальных случаях стоит уведомить пользователя об ошибках при загрузке файла. Если мы прочитаем вот эту страничку документации, то увидим, что ошибки на самом деле могут быть самыми разными.

Хороший код должен обрабатывать каждую из этих ошибок и выдавать соответствующую информацию пользователю. Мы же в учебном примере ограничимся только проверкой на 0, будет большим плюсом, если вы самостоятельно напишите обработку всех этих ошибок в своём коде. Итак, результат.

Код доступен только после покупки курса PHP для начинающих.

Проверяем расширение загружаемого файла

Ещё необходимо проверить то, что у загружаемого файла корректное расширение. Например, если мы хотим чтобы через форму загружали только картинки, то допустимыми расширениями для нас будут .jpg, .gif, .png.

Если этого не предусмотреть – то через форму загрузки можно будет загрузить какой-нибудь вредоносный скрипт. Представьте, что кто-то загрузил на сервер .php-скрипт, который удаляет все файлы в текущей директории, а затем просто запустил его, зайдя по адресу http://myproject.loc/uploads/very_bad_script.php. И это еще не самое страшное, что могут сделать злобные хакеры. Поэтому нужно всегда контролировать то, что пользователи загружают на сервер.

Получить расширение файла можно при помощи функции pathinfo(). Первым аргументом передаётся путь до файла, вторым – константа PATHINFO_EXTENSION.

Код доступен только после покупки курса PHP для начинающих.

В переменной $extension после это будет строка c расширением загруженного файла, например, png.
Нам остаётся только проверить, что расширение загружаемого файла находится в списке разрешенных. Давайте создадим массив со списком таких расширений и проверим наличие расширения загружаемого файла в списке разрешенных.

Код доступен только после покупки курса PHP для начинающих.

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

Результат

В ходе данного урока получили скрипт следующего содержания.

Код доступен только после покупки курса PHP для начинающих.

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

Домашнее задание
  • Позвольте загружать только файлы размером меньше 8Мб. Сделайте это с помощью сравнения с $_FILES['attachment']['size'].
  • Изучите директиву upload_max_filesize в файле php.ini. Установите её значение, равное 2M. Перезапустите веб-сервер. Попробуйте теперь загрузить файл, размером в 5Мб. Теперь обработайте соответствующую ошибку с помощью проверки значения $_FILES['attachment']['error'].
  • Разрешите загружать картинки с шириной не более 1280px и высотой не более 720px.
Читайте также
Комментарии (38)


fantasyz
$srcFileName = $file['name'];
$sizeFile = $file['size'];
$filePath = $file['tmp_name'];
$newFilePath = __DIR__ . '/upload/' . $srcFileName;
$image = getimagesize($filePath);
$limitWidth = 1280;
$limitHeight = 720;

1.

if ($sizeFile > 8000000) {
    $error = 'размер файла слишком большой';
}

2.

elseif ($file['error'] == UPLOAD_ERR_INI_SIZE) {
    $error = 'размер файла слишком большой';
}

3.

else if ($image['1'] > $limitWidth || $image['0'] > $limitHeight) {
    $error = 'разрешение картинки слишком велико';
}
ivashkevich

Очень хорошо!

Замечание по первому заданию - 8МБ это всё-таки 8 * 1024 * 1024. Можно прямо так в коде и записать.

А в третьем задании стоит воспользоваться функцией getimagesize(), она более надёжна, так как позволяет узнать размеры картинки на стороне сервера. Кроме того, она может вернуть false, что будет говорить о том, что картинка мягко говоря "неправильная". Цифры в вашем примере пришли из браузера - это менее надежно. Они могут прийти от клиента какими угодно. А могут и вовсе не прийти, и тогда будет warning, так как ключей 0 и 1 в массиве не окажется.

fantasyz

так я же применяю функцию getimagesize() к временному файлу вот тут $image = getimagesize($filePath); и беру из полученого массива соответствующие данные для сравнения с задаными

ivashkevich

Прошу прощения, не увидел. Тогда всё отлично. Единственное - переменную лучше назвать $imageSize.

fantasyz

Спасибо, исправлю)

1nSide

Почитал разобрался)

<?php

if (!empty($_FILES['attachment'])) {
    $file = $_FILES['attachment'];

    $srcFileName = $file['name'];
    $newFilePath = __DIR__ . '\upload' . $srcFileName;
    $fileSize = $file['size'];
    $limitBytes  = 1024 * 1024 * 8;
    $limitWidth  = 1280;
    $limitHeight = 768;
    $filePath = $file['tmp_name'];
    $image = getimagesize($filePath);

    $allowedExtensions = ['jpg', 'png', 'gif'];
    $extension = pathinfo($srcFileName, PATHINFO_EXTENSION);

    if ($fileSize > $limitBytes) {
        $error = 'Размер файла слишком большой';
    } elseif ($file['error'] == UPLOAD_ERR_INI_SIZE) {
        $error = 'Размер файла слишком большой';
    } elseif ($image[1] > $limitHeight || $image[0] > $limitWidth){
        $error = 'Привышенно допустимое разрешение картинки';
    } elseif (!in_array($extension, $allowedExtensions)) {
        $error = 'Загрузка файлов с таким расширением запрещена!';
    } elseif ($file['error'] !== UPLOAD_ERR_OK) {
        $error = 'Ошибка при загрузке файла.';
    } elseif (file_exists($newFilePath)) {
        $error = 'Файл с таким именем уже существует';
    } elseif (!move_uploaded_file($filePath, $newFilePath)) {
        $error = 'Ошибка при загрузке файла';
    } else {
        $result = 'http://myproject.loc/upload/upload.php' . $srcFileName;
    }
}

?>

<html>
<head>
    <title>Загрузка файла</title>
</head>
<body>
<?php if (!empty($error)): ?>
    <?= $error ?>
<?php elseif (!empty($result)): ?>
    <?= $result ?>
<?php endif; ?>
<br>
<form action="/upload/upload.php" method="post" enctype="multipart/form-data">
    <input type="file" name="attachment">
    <input type="submit">
</form>
</body>
</html>
ivashkevich

Отлично! :)

Nikolas

у меня вопрос, проверка условия if (!move_uploaded_file($file['tmp_name'], $newFilePath)) и сразу выполнит саму функцию move_uploaded_file и использует ее же в проверке условия?Мне казалось,что нужно ее сначала выполнить,после чего она вернет true или false и только потом использовать ее в проверке условия?

ivashkevich

Да, отработает именно так, как вы и написали. Сначала выполнится и вернёт результат, который сразу будет проверен в условии. Можно и в переменную положить, $isUploaded, например, а затем проверять её.

Fox-24

Еще один замечательный урок пройден :)

<?php

// Позвольте загружать только файлы размером меньше 8Мб. Сделайте это с помощью сравнения с $_FILES['attachment']['size'].
// Изучите директиву upload_max_filesize в файле php.ini. Установите её значение, равное 2M. Перезапустите веб-сервер.
// Попробуйте теперь загрузить файл, размером в 5Мб. Теперь обработайте соответствующую ошибку с помощью проверки значения $_FILES['attachment']['error'].
// Разрешите загружать картинки с шириной не более 1280px и высотой не более 720px.

if (!empty($_FILES['attachment'])) {
    $file = $_FILES['attachment'];
    $errorCode = $_FILES['attachment']['error'];
    $filePath = $_FILES['attachment']['tmp_name'];
    $fileSize = $_FILES['attachment']['size'];

    $srcFileName = $file['name'];
    $newFilePath = __DIR__ . '/uploads/' . $srcFileName;

    $allowedExtensions = ['jpg', 'png', 'gif'];
    $extension = pathinfo($srcFileName, PATHINFO_EXTENSION); //

    // Проверка на ошибки из $_FILES
    if ($errorCode !== UPLOAD_ERR_OK) {
        $error = [
            UPLOAD_ERR_INI_SIZE => 'Размер файла превысил значение upload_max_filesize в конфигурации PHP.',
            UPLOAD_ERR_FORM_SIZE => 'Размер загружаемого файла превысил значение MAX_FILE_SIZE в HTML-форме.',
            UPLOAD_ERR_PARTIAL => 'Загружаемый файл был получен только частично.',
            UPLOAD_ERR_NO_FILE => 'Файл не был загружен.',
            UPLOAD_ERR_NO_TMP_DIR => 'Отсутствует временная папка.',
            UPLOAD_ERR_CANT_WRITE => 'Не удалось записать файл на диск.',
            UPLOAD_ERR_EXTENSION => 'PHP-расширение остановило загрузку файла.',
        ];
        // Зададим неизвестную ошибку
        $unknownMessage = 'При загрузке файла произошла неизвестная ошибка.';
        // Если в массиве нет кода ошибки, скажем, что ошибка неизвестна
        $outputMessage = isset($error[$errorCode]) ? $error[$errorCode] : $unknownMessage;
        // Выведем название ошибки
        die($outputMessage);

    }

// Зададим ограничения для картинок
    $limitBytes = 1024 * 1024 * 2;
    $limitWidth = 1280;
    $limitHeight = 720;

    $image = getimagesize($filePath);   // В переменной $image массив с информацией о размерах картинки
    if (!in_array($extension, $allowedExtensions)) {
        $error = 'Загрузка файлов с таким расширением запрещена!';
    } elseif ($fileSize > $limitBytes) {
        $error = 'Размер изображения не должен превышать 2 Мбайт.';     // Если прквышает ограничение из $limitBytes
    } elseif ($image[1] > $limitHeight) {
        $error = 'Высота изображения не должна превышать 1280 точек.';  // Если прквышает ограничение из $limitWidth
    } elseif ($image[0] > $limitWidth) {
        $error = 'Ширина изображения не должна превышать 720 точек.';   // Если прквышает ограничение из $limitHeight
    } elseif (file_exists($newFilePath)) {
        $error = 'Файл с таким именем уже существует';
    } elseif (!move_uploaded_file($file['tmp_name'], $newFilePath)) {
        $error = 'Ошибка при загрузке файла';
    } else {
        $result = 'http://myproject.loc/uploads/' . $srcFileName;
    }
}

?>
<html>
<head>
    <title>Загрузка файла</title>
</head>
<body>
<?php if (!empty($error)): ?>
    <?= $error ?>
<?php elseif (!empty($result)): ?>
    <?= $result ?>
<?php endif; ?>
<br>
<form action="./upload.php" method="post" enctype="multipart/form-data">
    <input type="file" name="attachment">
    <input type="submit">
</form>
</body>
</html>
ivashkevich

Неплохо) Из улучшений - можно в текстах ошибок подставлять значения переменных с максимальным размером, высотой и шириной. Переделывать не надо - просто для размышления.

ArtemijeKA

1.

    $fileSize = $_FILES['attachment']['size'];

    if ($fileSize > 8000000) { // ############################################ 1
        $error = 'Загрузка файлов более чем 8Мб запрещена!';
    } elseif ...

3.

    } elseif ($file['error'] === UPLOAD_ERR_INI_SIZE) { // ################### 3
        $error = 'Размер принятого файла превысил максимально допустимый размер, который задан директивой 
        upload_max_filesize конфигурационного файла php.ini.';
    } elseif ...

4.

    $fileWidth = getimagesize($file['tmp_name'])['0'];
    $fileHeight = getimagesize($file['tmp_name'])['1'];

...

    } elseif ($fileWidth > 1280 && $fileHeight > 720) { // #################### 4
        $error = 'Загрузите картинку в пределах ширины не более 1280px и высотой не более 720px! Пожалуйста)';
    } else ...
ivashkevich

8 Мбайт это не 8000000 байт. Это 8 * 1024 * 1024.

ArtemijeKA

Cпасибо. Это я грубо округлил 8,388,608 байт

ivashkevich
} elseif ($fileWidth > 1280 && $fileHeight > 720) {

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

ArtemijeKA

Надо наверно

} elseif ($fileWidth > 1280 || $fileHeight > 720) {
Benya
if (!empty($_FILES['attachment'])) {
    $file = $_FILES['attachment'];

    $filePatch = $file['tmp_name'];

$srcFileName = $file['name'];
$scrFileSize = $file['size'];
$fileSizeMax =  8*1024*1024;
$fileMaxWidth = 1280;
$fileMaxHeight = 720;
    $fileSizeWidthHeight = getimagesize($filePatch);
$newFilePath = __DIR__ . '/uploads/' . $srcFileName;
    $allowedExtensions = ['jpg', 'png', 'gif'];
    $extension = pathinfo($srcFileName, PATHINFO_EXTENSION);
    if ($fileSizeWidthHeight[0] > $fileMaxHeight || $fileSizeWidthHeight[1] > $fileMaxWidth) {
        $error = 'Не допустимая ширина или высота!';
    }elseif ($scrFileSize > $fileSizeMax || ($file['error'] == UPLOAD_ERR_INI_SIZE)) {
        $error = 'Файл слишком большой!';
    }elseif (!in_array($extension, $allowedExtensions)) {
        $error = 'Загрузка файлов с таким расширением запрещена!';
    }elseif ($file['error'] !== UPLOAD_ERR_OK) {
    $error = 'Ошибка при загрузке файла.';
}elseif (file_exists(($newFilePath))) {
    $error = 'Файл с таким именем существует';
}elseif (!move_uploaded_file($file['tmp_name'], $newFilePath)) {
    $error = "Ошибка при загрузке файла";
}else {
    $result = 'http://myproject.loc/uploads/' . $srcFileName;
}
}

?>
ivashkevich

Хорошо! Только отступы нужно исправить, а то всё на одном уровне.

SBTesla
<?php
// проверяем получение  ключевых значений
if (!empty($_FILES['attachment'] ['size'] ['tmp_name'])) {
    // Проверяем размер файла
$maxFile = 1024*1024*8;
        if($_FILES['attachment'] ['size'] > $maxFile) {
            $error = 'Файл превышает допустимый размер';
            echo $error;
 } else {
             $file = $_FILES['attachment'];
        }
        /* Определяем переменные с размерами*/
        $image = getimagesize($filePatch);
        $limitWidth = 1280;
        $limitHeight = 720;
        // Проверяем загружаемый файл на размеры
        if ($image[1] > $limitWidth) {
            $error = 'Высота изображения не должна превышать 720 точек';
        }
        if ($image[0] > $limitHeight) {
            $error = 'Ширина изображения не должна превышать 1280 точек';
        }
}

$fileName = $file['name'];
$filePatch = __DIR__ . '/fileUpload/' . $fileName;

$allowedExtension = [ 'ipg' , 'png' , 'gif'];
$extension = pathinfo($fileName, PATHINFO_EXTENSION);
if (!in_array($extension, $allowedExtension)) {
    $error = 'Загрузка фалов с таким расширением запрещена';
}

// проверяем файл ли это и временный ли он
if ($file['error'] !== UPLOAD_ERR_OK){
    $error = 'ошибка при загрузке фала';
}
elseif (file_exists($filePatch)) {
    $error = 'Файл с таким именем существует';
}elseif
     (!move_uploaded_file($file['tmp_name'], $filePatch)){
     $error = 'Ошибка при загрузке';
} else {
          $result = 'http://site/upload/fileUpload' . $fileName;
     }

?>

Только у меня вопрос по getimagesize, В официальной документации предупреждают что бы не использовать ее для проверки изображения, а использовать Fileinfo.Отсюда вопрос может я неправильно написал и есть смысл использовать проверку getimagesize после того как проверим расширение файла?

ivashkevich

отлично!!! только дважды "http://" повторяется

SBTesla

Поправил

demyanovpaul@yandex.ru

Позвольте загружать только файлы размером меньше 8Мб. Сделайте это с помощью сравнения с $_FILES['attachment']['size'].

const MAX_FILE_SIZE = 8 * 1024 * 1024;
 if($file['size'] > MAX_FILE_SIZE ) {
        $error = 'Размер файла слишком свыше 8мб!';
    }

Изучите директиву upload_max_filesize в файле php.ini. Установите её значение, равное 2M. Перезапустите веб-сервер. Попробуйте теперь загрузить файл, размером в 5Мб. Теперь обработайте соответствующую ошибку с помощью проверки значения $_FILES['attachment']['error'].

if ($file['error'] == UPLOAD_ERR_INI_SIZE) {
        $error = 'Размер файла слишком большой';
    }

Разрешите загружать картинки с шириной не более 1280px и высотой не более 720px.

const MAX_HEIGHT_SIZE_IMG = 720;
const MAX_WIDTH_SIZE_IMG = 1280;

if ($imageUploadInfo[0] > MAX_WIDTH_SIZE_IMG || $imageUploadInfo[1] > MAX_HEIGHT_SIZE_IMG) {
        $error = 'Размер изображения не должен превышать ' . MAX_WIDTH_SIZE_IMG . 'x' . MAX_HEIGHT_SIZE_IMG . '!';
    }

Весь код

<?php
const MAX_FILE_SIZE = 8 * 1024 * 1024;
const MAX_HEIGHT_SIZE_IMG = 720;
const MAX_WIDTH_SIZE_IMG = 1280;

if (!empty($_FILES['attachment'])) {
    $file = $_FILES['attachment'];

    $srcFileName = $file['name'];
    $newFilePath = __DIR__ . '/uploads/' . $srcFileName;

    $allowedExtensions = ['jpg', 'png', 'gif'];
    $extension = pathinfo($srcFileName, PATHINFO_EXTENSION);

    $imageUploadInfo = getimagesize($file['tmp_name']);

    if($file['size'] > MAX_FILE_SIZE ) {
        $error = 'Размер файла слишком свыше 8мб!';
    } elseif ($file['error'] == UPLOAD_ERR_INI_SIZE) {
        $error = 'Размер файла слишком большой';
    } elseif ($imageUploadInfo[0] > MAX_WIDTH_SIZE_IMG || $imageUploadInfo[1] > MAX_HEIGHT_SIZE_IMG) {
        $error = 'Размер изображения не должен превышать ' . MAX_WIDTH_SIZE_IMG . 'x' . MAX_HEIGHT_SIZE_IMG . '!';
    } elseif (!in_array($extension, $allowedExtensions)) {
        $error = 'Загрузка файлов с таким расширением запрещена!';
    } elseif ($file['error'] !== UPLOAD_ERR_OK) {
        $error = 'Ошибка при загрузке файла.';
    } elseif (file_exists($newFilePath)) {
        $error = 'Файл с таким именем уже существует';
    } elseif (!move_uploaded_file($file['tmp_name'], $newFilePath)) {
        $error = 'Ошибка при загрузке файла';
    } else {
        $result = 'http://myproject.loc/uploads/' . $srcFileName;
    }
}
?>
<html>
<head>
    <title>Загрузка файла</title>
</head>
<body>
<?php if (!empty($error)): ?>
    <?= $error ?>
<?php elseif (!empty($result)): ?>
    <?= $result ?>
<?php endif; ?>
<br>
<form action="/upload.php" method="post" enctype="multipart/form-data">
    <input type="file" name="attachment">
    <input type="submit">
</form>
</body>
</html>
virtual2018
<body>
<?php if (!empty($error)): ?>
    <?= $error ?>
<?php elseif (!empty($result)): ?>
    <?= $result ?>
<?php endif; ?>
<br>

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

ivashkevich

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

lig7771991@list.ru

У меня не работает данный скрипт из примера, пишет -

Объект не найден!
Запрашиваемый ресурс не найден. Ссылка на странице неверна или устарела. Пожалуйста, сообщите автору этой страницы об ошибке.

Если Вы считаете, что это ошибка сервера, пожалуйста, сообщите об этом веб-мастеру.

И вообще некоторые скрипты из заданий. Может быть это из-за того что я использую XAMP а не OpenServer??

virtual2018

Вы очень мало предоставили информации по Вашей проблеме, однозначно могу сказать, что проблема не в XAMP. Рекомендую воспользоваться инструментом разработчика Хрома, чтобы определить какой именно объект не найден, а так же внимательно проверить правильно ли указано местоположение каталога uploads из задания.

ivashkevich

В самом начале курса я предупредил, что работаем в OpenServer. Выбираете что-то другое - разбирайтесь сами.

virtual2018
<?php
if (!empty($_FILES['attachment'])) {
    $file = $_FILES['attachment'];
    $srcFileName = $file['name'];
    $maxFileSize = 8 * 1024 * 1024; 
    $maxWidth = 1280;
    $maxHeight = 768;
    $newFilePath = __DIR__ . '/uploads/' . $srcFileName;
    $allowedExtensions = ['jpg', 'png', 'gif'];
    $extension = pathinfo($srcFileName, PATHINFO_EXTENSION);
    if (!in_array($extension, $allowedExtensions)) {
        $error = 'Загрузка файлов с таким расширением запрещена!';
    } elseif ($file['size'] > $maxFileSize) {
        $error = 'Размер файла превышает допустимое значение 8Mб';
    } elseif ($file['error'] == UPLOAD_ERR_INI_SIZE) {
        $error = 'Размер файла превышает допустимое значение ' . ini_get('upload_max_filesize');
    } elseif ($file['error'] == UPLOAD_ERR_PARTIAL) {
        $error = 'Файл не загрузился полностью. Повторите попытку';
    } elseif ($file['error'] == UPLOAD_ERR_NO_FILE) {
        $error = 'Файл не удалось загрузить';
    } elseif ($file['error'] == UPLOAD_ERR_NO_TMP_DIR) {
        $error = 'Недоступна временная папка для сохранения файла';
    } elseif ($file['error'] == UPLOAD_ERR_CANT_WRITE) {
        $error = 'Ошибка записи на диск';
    } elseif ($file['error'] !== UPLOAD_ERR_OK) {
        $error = 'Ошибка при загрузке файла.';
    } elseif (file_exists($newFilePath)) {
        $error = 'Файл с таким именем уже существует';
    } elseif (getimagesize($file['tmp_name'])[0] > $maxWidth || getimagesize($file['tmp_name'])[1] > $maxHeight) {
        $error = 'Некорректное разрешение файла';
    } elseif (!move_uploaded_file($file['tmp_name'], $newFilePath)) {
        $error = 'Ошибка при загрузке файла';
    } else {
        $result = 'http://myproject.loc/uploads/' . $srcFileName;
    }
}
?>
<html>
<head>
    <title>Загрузка файла</title>
</head>
<body>
<?php if (!empty($error)): ?>
    <?= $error ?>
<?php elseif (!empty($result)): ?>
    <?= $result ?>
<?php endif; ?>
<br>
<form action="/upload.php" method="post" enctype="multipart/form-data">
    <input type="file" name="attachment">
    <input type="submit">
</form>
</body>
</html>
Pavel-Tonk
$extension = pathinfo($srcFileName, PATHINFO_EXTENSION);

я извиняюсь, но ведь переменная $srcFileName хранит имя файла, а $newFilePath - путь, но работает и с той и с той переменной функция правильно или я что-то не понял >_<.

ivashkevich

Приведи конкретный пример с путями. Не понял пока вопроса.

Pavel-Tonk

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

$srcFileName = $file['name'];

в проверке расширения файла Вы используете её же, передавая функции pathinfo();

$extension = pathinfo($srcFileName, PATHINFO_EXTENSION);

Хотя первым аргументом должен передаваться путь к файлу.

ivashkevich

Имя файла - это тоже путь к файлу, просто он относительный (не полный). Получить от такого пути расширение - не проблема.

Pavel-Tonk

Спасибо за объяснение, теперь все понятно)

Pavel-Tonk
<?php 
if (!empty($_FILES['file'])) {
    $file = $_FILES['file'];
    $name = $file['name'];
    $tmp = $file['tmp_name'];
    $path = __DIR__.'/uploads/'.$name;
    $allowedExtensions = ['jpg', 'png', 'gif'];
    $extension = pathinfo($path, PATHINFO_EXTENSION);
    $image = getimagesize($tmp);
    print_r($image);
    if ($file['error'] !== 0) {
        switch ($file['error']) {
            case 1:
            case 2:
                $error = 'Размер загружаемого файла превысил лимит';
                break;
            case 3:
            case 4:
                $error = 'Файл загружен частично или не загружен';
                break;
            case 6:
                $error = 'Отсутствует временная папка';
                break;
            case 7:
                $error = 'Не удалось записать файл на диск';
                break;
            default:
                $error = 'Ошибок не установлено';
                break;
        };
    } else if (!in_array($extension, $allowedExtensions)) {
        $error = 'Загрузка файлов с таким расширением запрещена!';
    } else if ($image['0'] !== '900' || $image['1'] !== '900') {
        $error = 'Разрешение картинки превысило допустимые';
    } else if (file_exists($path)) {
        $error = 'Файл с таким именем существует';
    } else if (!move_uploaded_file($tmp, $path)) {
        $error = 'Ошибка при загрузке файла';
    } else {
        $result = $path;
    }
}

как-то так.

ivashkevich

Отличная обработка ошибок в switch-case!

Популярное за сутки
Сейчас читают
Логические задачи с собеседований