Загрузка файла php

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

В этой статье подробно разберем как сделать php-скрипт загрузки файла на сервер. Составим общее впечатление как это работает в связке с веб-сервером apache, а также рассмотрим тонкие моменты механизма загрузки файла.

Нам потребуется html-страница с формой для выбора файла, браузер, поддерживающий стандарт RFC-1867 (сейчас браузер без этого найти трудно) и, собственно, php-скрипт, в котором реализуем загрузку файла и сохранение его в нужную директорию. Загрузка файла происходит через обычный POST-запрос, однако нужно указать определенный параметр тега form - enctype - обратите внимание на html-код.

Чтобы сразу ответить на вопрос как загрузить несколько файлов на сервер одновременно с помощью php, будем писать именно такой html-код и php-скрипт. Если вам нужно реализовать загрузку только для одного файла - просто удалите лишние элементы формы input type="file", оставьте только один. Итак поехали дальше.

Исходный код формы на html-странице:

<form enctype="multipart/form-data" action="upload.php" method="post">
   <input type="hidden" name="MAX_FILE_SIZE" value="50000" />
   Выбери файл:
   <input name="userfile[]" type="file" />
   <input name="userfile[]" type="file" />
   <input name="userfile[]" type="file" />
   <input type="submit" value="Загрузить" />
</form>

Что значат эти параметры:

multipart/form-data
Параметр enctype тега form устанавливает MIME-тип для данных загружаемых вместе с данными формы. Если в форме присутствует поле для отправки файла, необходимо определить параметр enctype как multipart/form-data.
MAX_FILE_SIZE
Указывается максимальный размер файла в байтах. Параметр введен для экономии трафика, то есть размер файла проверяется на клиенте и, если файл больше, то он не будет закачан на сервер. Не следует полагаться только на этот параметр, так как его легко обойти, просто отредактировав html "на лету". Нужно также проверять размер загруженного файла в php-скрипте на сервере.
userfile[]
Мы написали имя поля формы со скобками [] чтобы была возможность, указав несколько полей для загрузки файла вместо одного, и не меняя скрипт, закачивать несколько файлов одновременно. То есть при отправке данных будет формироваться массив с элементами соответствующими загружаемым файлам.

Теперь создадим скрипт upload.php, в котором собственно реализуем загрузку файлов на php на веб-сервер:

<?
$path_to_files = './files/'; // путь для сохранения файлов
// если у нас несколько полей userfile[],
// отметаем те, в которые ничего не было выбрано
$good_name = array_filter($_FILES['userfile']['name']);
if (sizeof($good_name) != 0) { // если массив файлов не пустой
   foreach ($good_name as $key => $name) {
      $type = 	$_FILES['userfile']['type'][$key];
      $tmp_name = $_FILES['userfile']['tmp_name'][$key];
      $size = 	$_FILES['userfile']['size'][$key];
      // эта функция проверяет был ли загружен файл во временную директорию php
      if (!is_uploaded_file($tmp_name)) {
         echo "An error happened while loading. Failed.";
         continue;
      }
      // выковыриваем имя и расширение файла -
      $file_ext = substr($name, 1 + strrpos($name, "."));
      // - это может понадобиться, например, для сохранения в базу данных
      $file_name = substr($name, 0, strrpos($name, "."));
      // делаем реальный путь в файловой системе
      $real_path = realpath($path_to_files);
      // создаем в нашей директории временный файл с уникальным именем,
      // это делается для того, чтобы избежать одновременного
      // закачивания файлов с одним именем
      $temp_file_name = tempnam($real_path, "UPLF");
      // делаем новое, более привлекательное, имя файла для хранения на сервере
      $file_name = $temp_file_name."original.".strtolower($file_ext);
      // переносим загруженный временный файл в файл со
      // сделанным нами уникальным именем
      if (move_uploaded_file($tmp_name, $file_name)) {
         echo "Saved!";
         unlink($temp_file_name); // удаляем временный файл
      }else {
         echo "Failed!";
         continue;
      }
   }
}else {
   echo "No files were loaded.";
}
?>

Поясним:

После нажатия кнопки "Submit" в форме происходит загрузка файла на сервер - веб-сервер помещает файл во временную системную директорию (после окончания работы скрипта файл автоматически удаляется). Доступ к этим файлам и информации о них можно получить через глобальный массив $_FILES (используется начиная с версии PHP 4.1.0, раньше был $HTTP_POST_FILES). Собственно задача нашего скрипта - проверить информацию о файлах, которые мы загружаем, провести валидацию и перенести их из временной директории в заданную нужную.

Массив $_FILES имеет структуру вида:

$_FILES['userfile']['name']
Имя файла в файловой системе пользователя. После загрузки может меняться при некоторых условиях.
$_FILES['userfile']['type']
mime/type файла. Например "image/jpeg" (изображение в формате jpeg), "application/x-shockwave-flash" (flash-ролик), "application/msword" (документ MS-WORD). Более полную информацию о mime-типах файлов можно получить, например, в файле mime.types сервера Apache.
$_FILES['userfile']['size']
Размер файла в байтах.
$_FILES['userfile']['tmp_name']
Путь к файлу во временной директории на диске.
$_FILES['userfile']['error']
Код ошибки операции. Введен в версии PHP 4.2.0. Равен 0 если операция успешна.

Кроме того, о чем мы уже сказали, на загрузку файла на сервер могут влиять конфигурационные настройки PHP (смотрите ваш php.ini файл):

upload_tmp_dir
Эта директива в php.ini указывает директорию для временного хранения закачиваемых файлов. Имейте ввиду что она должна быть доступна для пользователя под которым запущен Apache, а также у нее должны быть выставлены права на запись для этого пользователя.
upload_max_filesize
Указывает максимальный размер загружаемого единичного файла, по умолчанию равна "2M" (2 мегабайта).
post_max_size
Общий максимальный размер для всех данных загружаемых методом POST. Для одновременной загрузки нескольких больших файлов нужно увеличить эту настройку. По умолчанию "8M" (8 мегабайт).
file_uploads
И, наконец, переключатель, запрещающий или разрешающий закачку файлов в общем. По умолчанию "On".

Настройки Apache:

Если вы все сделали правильно, но получаете что-нибудь вроде POST Method Not Allowed, возможно у вас неправильно сконфигурирован Apache. Ищите в файле httpd.conf строки похожие на:

<Limit POST>
   Order allow,deny
   Allow from all
</Limit>

Здесь ключевым словом является allow. Измените найденные строки на приведенный фрагмент, или, если не нашли, допишите фрагмент в httpd.conf.

Часто возникает проблема с тем, что загруженные бинарные файлы (картинки, видео и т.д.) оказываются битыми. Это может быть связано с автоматическим перекодированием поступающих данных сервером Apache (в частности это наблюдалось в Russian Apache). Есть несколько способов отменить перекодировку:

  • • Создать в директории скрипта файл .htaccess и внести в него строчку CharsetDisable On. Эта директива отключит "charset-processing module", отвечающий за перекодировку.
  • • Дописать в httpd.conf строки:
<Location />
   CharsetRecodeMultipartForms Off
</Location>

Директива CharsetRecodeMultipartForms отвечает за перекодировку данных, полученных POST-методом с заголовком Content-Type: multipart/form-data. Таким образом, все двоичные данные будут оставлены в первоначальном виде. Но при этом может возникнуть необходимость перекодировать текстовую часть запроса вручную, будьте внимательны.

Ну вот вроде все. Надеюсь ответил на вопрос как загрузить файл с помощью php на сервер. По крайней мере общие черты описал. Экспериментируйте со скриптом upload.php, смотрите в каком формате прилетают данные и все получится.

Добавить комментарий

Filtered HTML

  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Разрешённые HTML-теги: <a> <em> <i> <strong> <b> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd> <p> <br>
  • Строки и параграфы переносятся автоматически.

Plain text

  • HTML-теги не обрабатываются и показываются как обычный текст
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Строки и параграфы переносятся автоматически.
CAPTCHA
CAPTCHA на основе изображений
Введите код с картинки