Руководство по PHP
Пред. |  | След.

# Глава 38. Загрузка файлов на сервер

# Загрузка файлов методом POST

PHP способен принимать файл загружаемый при помощи любого браузера, поддерживающего стандарт RFC-1867 (в том числе Netscape Navigator 3 и выше, Microsoft Internet Explorer 3 с патчем от Microsoft или более поздние версии без патча). Это дает возможность загружать как текстовые, так и бинарные файлы. Вместе с PHP-аутентификацией и функциями для работы с файловой системой вы получаете полный контроль над тем, кому разрешено загружать файлы, и над тем, что делать с файлом после его загрузки.

> Смежные замечания по конфигурации: Также ознакомьтесь с описанием директив file_uploads, upload_max_filesize, upload_tmp_dir, max_input_time и post_max_size конфигурационного файла `php.ini`

Также следует заметить, что PHP поддерживает загрузку файлов методом PUT, который используется в клиентах Netscape Composer и W3C Amaya. Для получения более детальной документации обратитесь к разделу поддержка метода PUT

Страница для загрузки файлов может быть реализована при помощи специальной формы, которая выглядит примерно так:

Пример 38-1. Форма для загрузки файлов

    <form enctype="multipart/form-data" action="_URL_" method="post">
     <input type="hidden" name="MAX_FILE_SIZE" value="30000" />
     Отправить этот файл: <input name="userfile" type="file" />
     <input type="submit" value="Send File" />
    </form>

В приведенном выше примере "_URL_" необходимо заменить ссылкой на PHP-скрипт. Скрытое поле `MAX_FILE_SIZE`(значение необходимо указывать в байтах) должно предшествовать полю для выбора файла, и его значение является максимально допустимым размером принимаемого файла. Также следует убедиться, что в атрибутах формы вы указали `enctype="multipart/form-data"`, в противном случае загрузка файлов на сервер выполняться не будет.

Внимание

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

Переменные, определенные для загруженных файлов, зависят от версии PHP и текущей конфигурации. Суперглобальный массив $_FILES доступен начиная с PHP 4.1.0. Массив `$HTTP_POST_FILES` доступен начиная с PHP 4.0.0. Эти массивы содержат всю информацию о загруженных файлах. Использование `$_FILES` является более предпочтительным. В случае, если конфигурационная директива register_globals установлена значением on, дополнительно будут объявлены переменные с соответствующими именами. Начиная с версии 4.2.0 значением по умолчанию для опции register_globals является off.

Содержимое массива $_FILES для нашего примера приведено ниже. Обратите внимание, что здесь предполагается использование имени userfile для поля выбора файла, как и в приведенном выше примере. На самом деле имя поля может быть любым.

`$_FILES['userfile']['name']`

  Оригинальное имя файла на компьютере клиента.

`$_FILES['userfile']['type']`

  Mime-тип файла, в случае, если браузер предоставил такую информацию. Пример: `"image/gif"`.

`$_FILES['userfile']['size']`

  Размер в байтах принятого файла.

`$_FILES['userfile']['tmp_name']`

  Временное имя, с которым принятый файл был сохранен на сервере.

`$_FILES['userfile']['error']`

  Код ошибки, которая может возникнуть при загрузке файла. Ключ ['error'] был добавлен в PHP 4.2.0

> Замечание: В PHP 4.1.0 и более ранних версиях описанный выше массив назывался `$HTTP_POST_FILES` и не являлся суперглобальным, в отличие от `$_FILES`. В PHP 3 массив `$HTTP_POST_FILES` не определен.

В случае, если register_globals установлена значением on в конфигурационном файле `php.ini`, будут доступны дополнительные переменные. Например, `$userfile_name` будет эквивалентна переменной `$_FILES['userfile']['name']`, а `$userfile_type` соответствует `$_FILES['userfile']['type']`, и так далее. Не стоит забывать, что начиная с PHP 4.2.0 для директивы register_globals значение по умолчанию off. Рекомендуется не полагаться на значение этой директивы.

По умолчанию принятые файлы сохраняются на сервере в стандартной временной папке до тех пор, пока не будет задана другая директория при помощи директивы upload_tmp_dir конфигурационного файла `php.ini`. Директорию сервера по умолчанию можно сменить, установив переменную `TMPDIR` для окружения, в котором выполняется PHP. Установка переменной `TMPDIR` при помощи функции putenv() внутри PHP-скрипта работать не будет. Эта переменная окружения также может использоваться для того, чтобы удостовериться, что другие операции также работают с принятыми файлами.

Пример 38-2. Проверка загружаемых на сервер файлов

Для получения более детальной информации вы можете ознакомится с описанием функций is_uploaded_file() и move_uploaded_file(). Следующий пример принимает и обрабатывает загруженный при помощи формы файл.

`<?php
// В PHP 4.1.0 и более ранних версиях следует использовать $HTTP_POST_FILES
// вместо $_FILES.
$uploaddir = '/var/www/uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
print "<pre>";
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
print "File is valid, and was successfully uploaded. ";
print "Here's some more debugging info:\n";
print_r($_FILES);
} else {
print "Possible file upload attack! Here's some debugging info:\n";
print "Possible file upload attack! Дополнительная отладочная информация:\n";
print_r($_FILES);
}
print "</pre>";
?>`

PHP-скрипт, принимающий загруженный файл, должен реализовывать логику, необходимую для определения дальнейших действий над принятым файлом. Например, вы можете проверить переменную `$_FILES['userfile']['size']`, чтобы отсечь слишком большие или слишком маленькие файлы. Также вы можете использовать переменную `$_FILES['userfile']['type']` для исключения файлов, которые не удовлетворяют критерию касательно типа файла. Начиная с PHP 4.2.0 вы можете использовать `$_FILES['userfile']['error']` и разъяснение сообщений об ошибках при реализации вашей логики. Независимо от того, какую модель поведения вы выбрали, вы должны удалить файл из временной папки или переместить его в другую директорию.

В случае, если при отправке формы файл выбран не был, PHP установит переменную `$_FILES['userfile']['size']` значением 0, а переменную `$_FILES['userfile']['tmp_name']` - пустой строкой. none.

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

Пред. | Начало | След.
Работа с XForms | Уровень выше | Разъяснение сообщений об ошибках