Загрузка файлов на сайт с помощью PHP-скрипта
Сегодня я хочу рассказать вам о разнообразных ситуациях, в которых требуется загрузка файлов на сайт с помощью PHP-скриптов. Постараюсь привести примеры, как самой простой загрузки файла, так и мультизагрузки с применением move uploaded file PHP.

Простая загрузка файлов на сайт при помощи PHP
Вам не составит труда написать собственный PHP-скрипт для загрузки файлов на сервер. Прежде всего, нужно создать HTML-форму с полем file input. Затем привязать к ней PHP-скрипт, который переместит файл в указанную директорию. Чтобы закачать файл на сервер с помощью PHP-скрипта, выполните следующие действия:
Создайте простую HTML-форму: потребуется простая форма с возможностью указания файла. Она размещается в файле basic.php:
<html>
<head>
<title>Basic File Upload</title>
</head>
<body>
<h1>Basic File Upload</h1>
<form method="post" action="basic.php" enctype="multipart/form-data">
<label for="inputfile">Upload File</label>
<input type="file" id="inputfile" name="inputfile"></br>
<input type="submit" value="Click To Upload">
</form>
</body>
</html>
Приведенный выше код необходим для создания формы. Как только пользователь выбирает файл и нажимает кнопку Upload, форма передаст данные с помощью метода POST на этой же странице, так как в качестве обработчика указан файл basic.php:
Важно: не забудьте добавить enctype=”multipart/form-data” в тег <form>.

Создаем PHP-скрипт для обработки формы загрузки. В PHP вся информация о загруженных файлах содержится в глобальной переменной $_FILES. То есть, используя $_FILES, можно проверить, был ли загружен файл. Если файл был загружен, то можно переместить его в нужную директорию при помощи функции move_uploaded_file PHP:
<?php
if(isset($_FILES) && $_FILES['inputfile']['error'] == 0){ // Проверяем, загрузил ли пользователь файл
$destiation_dir = dirname(__FILE__) .'/'.$_FILES['inputfile']['name']; // Директория для размещения файла
move_uploaded_file($_FILES['inputfile']['tmp_name'], $destiation_dir ); // Перемещаем файл в желаемую директорию
echo 'File Uploaded'; // Оповещаем пользователя об успешной загрузке файла
}
else{
echo 'No File Uploaded'; // Оповещаем пользователя о том, что файл не был загружен
}
?>
Приведенный выше код проверяет, загрузил ли пользователь файл. Если файл загружен, то мы перемещаем файл в указанную директорию. В приведенном выше скрипте мы перемещаем файл в ту же папку, где находится файл basic.php.
Ниже приведена полная версия PHP move uploaded file примера:
<?php
if(isset($_FILES) && $_FILES['inputfile']['error'] == 0){ // Проверяем, загрузил ли пользователь файл
$destiation_dir = dirname(__FILE__) .'/'.$_FILES['inputfile']['name']; // Директория для размещения файла
move_uploaded_file($_FILES['inputfile']['tmp_name'], $destiation_dir ); // Перемещаем файл в желаемую директорию
echo 'File Uploaded'; // Оповещаем пользователя об успешной загрузке файла
}
else{
echo 'No File Uploaded'; // Оповещаем пользователя о том, что файл не был загружен
}
?>
<html>
<head>
<title>Basic File Upload</title>
</head>
<body>
<h1>Basic File Upload</h1>
<form method="post" action="basic.php" enctype="multipart/form-data">
<label for="inputfile">Upload File</label>
<input type="file" id="inputfile" name="inputfile"></br>
<input type="submit" value="Click To Upload">
</form>
</body>
</html>
Пожалуйста, не тестируйте этот PHP move uploaded file пример на сервере. Он не отвечает требованиям безопасности, и был создан специально для того, чтобы наглядно показать, как загружать файлы с помощью PHP.
Вопрос: Почему приведенный выше скрипт небезопасен?
Ответ: С помощью скрипта, приведенного выше, можно загрузить файл любого типа на сервер. То есть, если вы используете скрипт в таком виде на “живом” сервере, то любой хакер сможет загрузить собственные PHP-скрипты, и взломать ваш сайт и сервер.
Чуть позже мы подробнее поговорим о защите скрипта для загрузки файлов на сервер.
Что такое $_FILES?
$_FILES – это глобальная переменная в PHP наподобие $_POST или $_GET. Она представляет собой ассоциативный массив, в котором находится информация о загруженном файле с помощью метода HTTP POST.
То есть, если выполнить print_r($_FILES) для приведенного выше скрипта, то мы получим следующую информацию:
Array
(
[inputfile] => Array
(
[name] => upload-file-php.jpg
[type] => image/jpeg
[tmp_name] => /Applications/XAMPP/xamppfiles/temp/phpcQiYhh
[error] => 0
[size] => 6887
)
)
То есть, для каждого поля <input type=”file” name=”inputfile“/> в массиве создается элемент. Если вы создадите <input type=”file” name=”test”>, то название элемента также будет изменено на test. Например:
Array
(
[test] => Array
(
[name] => upload-file-php.jpg
[type] => image/jpeg
[tmp_name] => /Applications/XAMPP/xamppfiles/temp/phpcQiYhh
[error] => 0
[size] => 6887
)
)
Теперь для каждого input file, перемещаемого с помощью move uploaded file PHP, создается пять элементов (name, type, tmp_name, error, size). Давайте познакомимся с этими элементами поближе:
- name: содержит название загруженного пользователем файла. Если вы загрузите файл abc.txt в браузер, то элемент name получит название abc.txt;
- type: тип загруженного файла или mime-type, если точнее. Для файла JPG этот элемент будет иметь значение image/jpeg. Если загрузить текст, то элемент получит значение text/plain. Для разных типов файлов разным будет и mime-type. Ниже приведены самые распространенные mime-типы:
- JPEG: image/jpeg;
- PNG: image/png;
- Текст: text/plain;
- Word: application/msword.
- tmp_name: временное расположение для загруженного файла. Этот путь можно изменить в переменной upload_tmp_dir, указанной в файле php.ini.
- error: информация об ошибке. Включает в себя тип ошибки, возникшей в процессе загрузки. Например, когда размер файла превышает максимальный или когда не был указан файл для загрузки. Для любой возникшей ошибки имеется числовое значение и константа. Ниже приведен полный список ошибок, которые могут возникнуть в PHP move uploaded file примере:
- UPLOAD_ERR_OK (значение 0). Означает, что файл был успешно загружен без ошибок;
- UPLOAD_ERR_INI_SIZE (значение 1). Размер файла превышает указанный в переменной upload_max_filesize в файле php.ini;
- UPLOAD_ERR_FORM_SIZE (значение 2). Размер файла превышает установленное в переменной формы MAX_FILE_SIZE значение;
- UPLOAD_ERR_PARTIAL (значение 3). Файл загружен не полностью;
- UPLOAD_ERR_NO_FILE (значение 4). Отсутствует файл для загрузки;
- UPLOAD_ERR_NO_TMP_DIR (значение 6). Указанной директории для временного хранения не существует;
- UPLOAD_ERR_CANT_WRITE (значение 7). Невозможно записать файл на диск.
- size: размер загруженного файла в байтах.
Что такое move_uploaded_file?
move_uploaded_file представляет собой функцию, которая перемещает загруженный файл из временной директории в папку назначения. Перед перемещением move_uploaded_file PHP проверяет, был ли загружен файл, указанный в HTTP-методе post.
Если файл был успешно перемещен, то вы получите ответ true или false. В первом примере мы использовали следующую строку кода:
move_uploaded_file($_FILES['inputfile']['tmp_name'], $destiation_dir )
А теперь давайте сделаем красиво, и выведем информацию:
if(move_uploaded_file($_FILES['inputfile']['tmp_name'], $destiation_dir )){
echo "File Uploaded"
}
else{
echo "File Not uploaded"
}
Изменяем лимит размера загружаемого файла
У каждой формы для загрузки файлов должен быть установлен лимит размера, иначе пользователи станут загружать увесистые файлы. Выставить ограничение на move uploaded file PHP можно двумя способами:
- В файле PHP.ini есть специальная переменная upload_max_filesize, которая отвечает за максимальный размер загружаемых файлов. Далее приведена строчка из php.ini, которая ограничивает размер загружаемых файлов до 20 Мб: upload_max_filesize = 20M.
- Если загружаемый файл будет иметь больший размер, то пользователь получит ошибку UPLOAD_ERR_INI_SIZE или значение «2» в переменной $_FILES. Важно учесть, что значение переменной upload_max_filesize не должно превышать значение переменной post_max_size, указанной в php.ini;
- Ограничить размер загружаемого файла можно, поместив скрытый элемент ввода с названием UPLOAD_ERR_INI_SIZE в форму загрузки. Сделать это можно так: <input type="hidden" name="MAX_FILE_SIZE" value="50000" />.
Если нужно сильно увеличить filesize, то не забудьте изменить время исполнения php-скриптов.
Как обезопасить PHP-скрипт загрузки файлов
Теперь вы умеете ограничивать размер загружаемых файлов и знаете, как определить типы файлов, которые загружают пользователи. Пришло время позаботиться о безопасности нашего PHP move uploaded file примера.
В качестве примера сделаем так, чтобы пользователи не могли загружать jpeg-файлы размером свыше 1 Мб. Установите соответствующее ограничение в переменной upload_max_filesize файла php.ini. Ниже приведена улучшенная версия скрипта:
<?php
ini_set('upload_max_filesize', '1M'); //ограничение в 1 мб
if ($_SERVER['REQUEST_METHOD'] == "POST" ) {
if ($_FILES['inputfile']['error'] == UPLOAD_ERR_OK && $_FILES['inputfile']['type'] == 'image/jpeg') { //проверка на наличие ошибок
$destiation_dir = dirname(__FILE__) . '/' . $_FILES['inputfile']['name']; // директория для размещения файла
if (move_uploaded_file($_FILES['inputfile']['tmp_name'], $destiation_dir)) { //перемещение в желаемую директорию
echo 'File Uploaded'; //оповещаем пользователя об успешной загрузке файла
} else {
echo 'File not uploaded';
}
} else {
switch ($_FILES['inputfile']['error']) {
case UPLOAD_ERR_FORM_SIZE:
case UPLOAD_ERR_INI_SIZE:
echo 'File Size exceed';
brake;
case UPLOAD_ERR_NO_FILE:
echo 'FIle Not selected';
break;
default:
echo 'Something is wrong';
}
}
}
?>
<html>
<head>
<title>Secure File Upload</title>
</head>
<body>
<h1>Secure File Upload</h1>
<form method="post" action="secure.php" enctype="multipart/form-data">
<label for="inputfile">Upload File</label>
<input type="file" id="inputfile" name="inputfile"></br>
<input type="submit" value="Click To Upload">
</form>
</body>
</html>
Мультизагрузка файлов при помощи PHP-скрипта
Можно загружать сразу несколько файлов при помощи $_FILES и move_uploaded_file PHP. Ниже я расскажу вам о двух способах мультизагрузки файлов с помощью PHP-скрипта
- Используя разные имена Input.
- Используя одно и то же имя input, но с привлечением массива.
1. Используя разные имена Input:
Можно загружать сразу несколько файлов, используя несколько элементов ввода. Как уже говорилось ранее, если мы создаем несколько элементов input, то в $_FILES будет создано несколько основных элементов. Например, для приведенной ниже формы:
<input type="file" id="profilepic" name="profilepic">
<input type="file" id="resume" name="resume">
$_FILES представит массив следующего содержания:
Array
(
[profilepic] => Array
(
[name] => 20141002_094257.jpg
[type] => image/jpeg
[tmp_name] => /Applications/XAMPP/xamppfiles/temp/phpoBWrBZ
[error] => 0
[size] => 2669096
)
[resume] => Array
(
[name] => 20141002_094247.jpg
[type] => image/jpeg
[tmp_name] => /Applications/XAMPP/xamppfiles/temp/phpjwUmVZ
[error] => 0
[size] => 2207657
)
)
Приведенный ниже PHP move uploaded file пример нужно писать с учетом того, что один элемент предназначен для аватарки (изображение), а другой – для загрузки резюме (файла в формате .doc):
<?php
if ($_SERVER['REQUEST_METHOD'] == "POST" ) {
if ($_FILES['profilepic']['error'] == UPLOAD_ERR_OK && $_FILES['profilepic']['type'] == 'image/jpeg') { // Проверяем на наличие ошибок
$destiation_dir = dirname(__FILE__) . '/' . $_FILES['profilepic']['name']; // Директория для размещения файла
if (move_uploaded_file($_FILES['profilepic']['tmp_name'], $destiation_dir)) { // Перемещаем файл в желаемую директорию
echo 'Profile Pic Uploaded'; // Оповещаем пользователя об успешной загрузке файла
} else {
echo 'Profile Pic not uploaded';
}
} else {
switch ($_FILES['profilepic']['error']) {
case UPLOAD_ERR_FORM_SIZE:
case UPLOAD_ERR_INI_SIZE:
echo 'Profile Pic Size exceed';
brake;
case UPLOAD_ERR_NO_FILE:
echo 'Profile Pic Not selected';
break;
default:
echo 'Something is wrong with Profile PIC';
}
}
if ($_FILES['resume']['error'] == UPLOAD_ERR_OK && $_FILES['resume']['type'] == ' application/msword') { // Проверяем на наличие ошибок
$destiation_dir = dirname(__FILE__) . '/' . $_FILES['resume']['name']; // Директория для размещения файла
if (move_uploaded_file($_FILES['resume']['tmp_name'], $destiation_dir)) { // Перемещаем файл в желаемую директорию
echo 'resume Uploaded'; // Оповещаем пользователя об успешной загрузке файла
} else {
echo 'resume not uploaded';
}
} else {
switch ($_FILES['resume']['error']) {
case UPLOAD_ERR_FORM_SIZE:
case UPLOAD_ERR_INI_SIZE:
echo 'resume Size exceed';
brake;
case UPLOAD_ERR_NO_FILE:
echo 'resume Not selected';
break;
default:
echo 'Something is wrong with resume';
}
}
}
?>
<html>
<head>
<title>Multiple File Upload</title>
</head>
<body>
<h1>Multiple File Upload</h1>
<form method="post" action="multiple.php" enctype="multipart/form-data">
<label for="profilepic">Profile Pic</label>
<input type="file" id="profilepic" name="profilepic"></br>
<label for="resume">Resume</label>
<input type="file" id="resume" name="resume"></br>
<input type="submit" value="Click To Upload">
</form>
</body>
</html>
2. Используем одно поле input, но с применением массива:
Как и в случае с другими типами input, для move uploaded file PHP мы можем использовать массив с input type, указанным в php. То есть:
<input type="file" id="pic" name="pic[]">
<input type="file" id="pic" name="pic[]">
<input type="file" id="pic" name="pic[]">
То есть, для приведенного выше HTML, $_FILES предоставит данные со следующей структурой:
Array
(
[pic] => Array
(
[name] => Array
(
[0] => upload-file-php.jpg
[1] => variable-scope-php.jpg
[2] => magic-constants.jpg
)
[type] => Array
(
[0] => image/jpeg
[1] => image/jpeg
[2] => image/jpeg
)
[tmp_name] => Array
(
[0] => /Applications/XAMPP/xamppfiles/temp/phpML5kOy
[1] => /Applications/XAMPP/xamppfiles/temp/phpNZbuw7
[2] => /Applications/XAMPP/xamppfiles/temp/phpO8VFAk
)
[error] => Array
(
[0] => 0
[1] => 0
[2] => 0
)
[size] => Array
(
[0] => 6887
[1] => 8036
[2] => 9967
)
)
)
Скачать код, использованный в статье