/* Значение $_FILES[‘attachment’] представляет собой массив с пятью ключами. Давайте рассмотрим каждый из элементов этого массива более подробно.
name – имя файла, переданное из браузера; type – тип файла, в моём случае это image/png; tmp_name – путь до временного файла, который загрузился на сервер, но если с ним до конца запроса ничего не сделать, то он удалится; error – код ошибки при загрузке файла, если 0 – то ошибки нет. Изучите возможные коды ошибок вот тут; size – размер загруженного файла в байтах. Как мы уже сказали, пока что на сервере создан временный файл. Чтобы его сохранить нужно вызвать специальную функцию, которая переместит его из временной папки в нужную нам папку (в нашем случае это папка uploads). Эта функция — move_uploaded_file() . Первым аргументом она принимает путь до временного файла (в нашем случае — $_FILES[‘attachment’][‘tmp_name’]), а вторым аргументом – путь, по которому нужно его сохранить. Функция вернёт true, если всё ок, и false, если что-то пошло не так.
ВНИМАНИЕ! Для перемещения временного файла в нужную вам папку стоит всегда использовать функцию move_uploaded_file(). Она предварительно проверяет, что указанный файл действительно является временным загруженным файлом, а не чем-то ещё. Другие функции для копирования файлов не подойдут, так как они эту проверку не выполняют, а это небезопасно. Кому интересно – можете подробнее прочитать тут.
В простейшем виде скрипт для загрузки файла на сервер будет выглядеть следующим образом.
Если сейчас выбрать файл и нажать на кнопку “Отправить”, то скрипт вернёт нам адрес загруженного файла.
Мы можем открыть этот адрес в новой вкладке, и убедиться, что действительно файл доступен по этому адресу. Ну и если посмотрим в папку uploads, то тоже увидим, что наш файлик теперь там валяется.
Этот скрипт ещё очень сырой, давайте его доработаем.
Проверка на существующий файл с таким же именем Первое, что приходит на ум – убедиться, что файл с таким именем не загружался ранее. Иначе мы рискуем перезатереть что-нибудь важное. Давайте проверим существование такого файла с помощью функции file_exists() .
elseif (!move_uploaded_file($file['tmp_name'], $newFilePath)) < $error = 'Ошибка при загрузке файла'; >else < $result = 'http://myproject.loc/uploads/' . $srcFileName; >> ?> .
Обработка ошибок при загрузке файлов Теперь вспомним об элементе массива по ключу error. Как мы помним, при отсутствии ошибок там будет 0. Во всех остальных случаях стоит уведомить пользователя об ошибках при загрузке файла. Если мы прочитаем вот эту страничку документации, то увидим, что ошибки на самом деле могут быть самыми разными.
Хороший код должен обрабатывать каждую из этих ошибок и выдавать соответствующую информацию пользователю. Мы же в учебном примере ограничимся только проверкой на 0, будет большим плюсом, если вы самостоятельно напишите обработку всех этих ошибок в своём коде. Итак, результат.
elseif (file_exists($newFilePath)) < $error = 'Файл с таким именем уже существует'; >elseif (!move_uploaded_file($file['tmp_name'], $newFilePath)) < $error = 'Ошибка при загрузке файла'; >else < $result = 'http://myproject.loc/uploads/' . $srcFileName; >> ?> .
Проверяем расширение загружаемого файла Ещё необходимо проверить то, что у загружаемого файла корректное расширение. Например, если мы хотим чтобы через форму загружали только картинки, то допустимыми расширениями для нас будут .jpg, .gif, .png.
Если этого не предусмотреть – то через форму загрузки можно будет загрузить какой-нибудь вредоносный скрипт. Представьте, что кто-то загрузил на сервер .php-скрипт, который удаляет все файлы в текущей директории, а затем просто запустил его, зайдя по адресу http://myproject.loc/uploads/very_bad_script.php. И это еще не самое страшное, что могут сделать злобные хакеры. Поэтому нужно всегда контролировать то, что пользователи загружают на сервер.
Получить расширение файла можно при помощи функции pathinfo(). Первым аргументом передаётся путь до файла, вторым – константа PATHINFO_EXTENSION.
$extension = pathinfo($srcFileName, PATHINFO_EXTENSION);
В переменной $extension после это будет строка c расширением загруженного файла, например, png. Нам остаётся только проверить, что расширение загружаемого файла находится в списке разрешенных. Давайте создадим массив со списком таких расширений и проверим наличие расширения загружаемого файла в списке разрешенных.
$allowedExtensions = ['jpg', 'png', 'gif']; $extension = pathinfo($srcFileName, PATHINFO_EXTENSION); if (!in_array($extension, $allowedExtensions))
Теперь, если вы попробуете загрузить файл с каким-то другим расширением, то скрипт на нас ругнётся.
Результат В ходе данного урока получили скрипт следующего содержания.
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; >> ?>
Есть ещё несколько проверок, которые было бы неплохо провести, прежде чем позволить загрузить файл на сервер. О них вы узнаете в домашнем задании.
Источник
Загрузка файлов на сервер PHP
В статье приведен пример формы и php-скрипта для безопасной загрузки файлов на сервер, возможные ошибки и рекомендации при работе с данной темой. HTML-форма отправит файл только методом POST и с атрибутом enctype=»multipart/form-data» .
Файл upload.php Поддерживает как одиночную загрузку файла так и множественную (multiple) без изменения кода. Проверка на все возможные ошибки которые могут возникнуть при загрузке файлов. Имена файлов переводятся в транслит и удаляются символы которые будут в дальнейшем мешать вывести их на сайте. Есть возможность указать разрешенные и запрещенные для загрузки расширения файлов. // Название $input_name = 'file'; // Разрешенные расширения файлов. $allow = array(); // Запрещенные расширения файлов. $deny = array( 'phtml', 'php', 'php3', 'php4', 'php5', 'php6', 'php7', 'phps', 'cgi', 'pl', 'asp', 'aspx', 'shtml', 'shtm', 'htaccess', 'htpasswd', 'ini', 'log', 'sh', 'js', 'html', 'htm', 'css', 'sql', 'spl', 'scgi', 'fcgi' ); // Директория куда будут загружаться файлы. $path = __DIR__ . '/uploads/'; if (isset($_FILES[$input_name])) < // Проверим директорию для загрузки. if (!is_dir($path)) < mkdir($path, 0777, true); >// Преобразуем массив $_FILES в удобный вид для перебора в foreach. $files = array(); $diff = count($_FILES[$input_name]) - count($_FILES[$input_name], COUNT_RECURSIVE); if ($diff == 0) < $files = array($_FILES[$input_name]); >else < foreach($_FILES[$input_name] as $k =>$l) < foreach($l as $i =>$v) < $files[$i][$k] = $v; >> > foreach ($files as $file) < $error = $success = ''; // Проверим на ошибки загрузки. if (!empty($file['error']) || empty($file['tmp_name'])) < switch (@$file['error']) < case 1: case 2: $error = 'Превышен размер загружаемого файла.'; break; case 3: $error = 'Файл был получен только частично.'; break; case 4: $error = 'Файл не был загружен.'; break; case 6: $error = 'Файл не загружен - отсутствует временная директория.'; break; case 7: $error = 'Не удалось записать файл на диск.'; break; case 8: $error = 'PHP-расширение остановило загрузку файла.'; break; case 9: $error = 'Файл не был загружен - директория не существует.'; break; case 10: $error = 'Превышен максимально допустимый размер файла.'; break; case 11: $error = 'Данный тип файла запрещен.'; break; case 12: $error = 'Ошибка при копировании файла.'; break; default: $error = 'Файл не был загружен - неизвестная ошибка.'; break; >> elseif ($file['tmp_name'] == 'none' || !is_uploaded_file($file['tmp_name'])) < $error = 'Не удалось загрузить файл.'; >else < // Оставляем в имени файла только буквы, цифры и некоторые символы. $pattern = "[^a-zа-яё0-9,~!@#%^-_\$\?\(\)\\[\]\.]"; $name = mb_eregi_replace($pattern, '-', $file['name']); $name = mb_ereg_replace('[-]+', '-', $name); // Т.к. есть проблема с кириллицей в названиях файлов (файлы становятся недоступны). // Сделаем их транслит: $converter = array( 'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd', 'е' => 'e', 'ё' => 'e', 'ж' => 'zh', 'з' => 'z', 'и' => 'i', 'й' => 'y', 'к' => 'k', 'л' => 'l', 'м' => 'm', 'н' => 'n', 'о' => 'o', 'п' => 'p', 'р' => 'r', 'с' => 's', 'т' => 't', 'у' => 'u', 'ф' => 'f', 'х' => 'h', 'ц' => 'c', 'ч' => 'ch', 'ш' => 'sh', 'щ' => 'sch', 'ь' => '', 'ы' => 'y', 'ъ' => '', 'э' => 'e', 'ю' => 'yu', 'я' => 'ya', 'А' => 'A', 'Б' => 'B', 'В' => 'V', 'Г' => 'G', 'Д' => 'D', 'Е' => 'E', 'Ё' => 'E', 'Ж' => 'Zh', 'З' => 'Z', 'И' => 'I', 'Й' => 'Y', 'К' => 'K', 'Л' => 'L', 'М' => 'M', 'Н' => 'N', 'О' => 'O', 'П' => 'P', 'Р' => 'R', 'С' => 'S', 'Т' => 'T', 'У' => 'U', 'Ф' => 'F', 'Х' => 'H', 'Ц' => 'C', 'Ч' => 'Ch', 'Ш' => 'Sh', 'Щ' => 'Sch', 'Ь' => '', 'Ы' => 'Y', 'Ъ' => '', 'Э' => 'E', 'Ю' => 'Yu', 'Я' => 'Ya', ); $name = strtr($name, $converter); $parts = pathinfo($name); if (empty($name) || empty($parts['extension'])) < $error = 'Недопустимое тип файла'; >elseif (!empty($allow) && !in_array(strtolower($parts['extension']), $allow)) < $error = 'Недопустимый тип файла'; >elseif (!empty($deny) && in_array(strtolower($parts['extension']), $deny)) < $error = 'Недопустимый тип файла'; >else < // Чтобы не затереть файл с таким же названием, добавим префикс. $i = 0; $prefix = ''; while (is_file($path . $parts['filename'] . $prefix . '.' . $parts['extension'])) < $prefix = '(' . ++$i . ')'; >$name = $parts['filename'] . $prefix . '.' . $parts['extension']; // Перемещаем файл в директорию. if (move_uploaded_file($file['tmp_name'], $path . $name)) < // Далее можно сохранить название файла в БД и т.п. $success = 'Файл «' . $name . '» успешно загружен.'; >else < $error = 'Не удалось загрузить файл.'; >> > // Выводим сообщение о результате загрузки. if (!empty($success)) < echo '' . $success . '
'; > else < echo '' . $error . '
'; > > >
Возможные проблемы