Загрузка файлов в PHP. Как обработать и сохранить присланные данные?

загрузка файлов в php. как обработать и сохранить присланные данные?

Принципы загрузки файлов

Загрузка файла на сервер может быть выполнена как с помощью веб-формы, расположенной на странице сайта, так и прямым программным запросом. Для PHP-интерпретатора способ передачи файла не имеет значения. Спецификация HTTP-протокола приводит эти операции к единообразному виду. Если вы плохо знакомы с данной темой, рекомендуем изучить статью «загрузка файлов через HTML-формы».

Любой загружаемый файл будет помещен в специальную директорию для временного хранения, а связанная с ним информация добавлена в суперглобальный массив $_FILES. Если не переместить файл в другое место, после завершения скрипта произойдет его бесследное удаление. Директория временного хранения определяется настройкой upload_tmp_dir конфигурационного файла php.ini.

Суперглобальный массив $_FILES

Если вместе с текущим запросом были загружены файлы, PHP-интерпретатор автоматически заполнит суперглобальный массив $_FILES соответствующей информацией. Его структура довольно проста. Элементы массива соответствуют именам параметров HTTP-запроса. Например, ваша веб-форма содержит поле загрузки файла с атрибутом «name="upload-file"». В таком случае информация будет добавлена в $_FILES['upload-file'].

Содержимое массива $_FILES:

  • $_FILES['поле-запроса']['name'] — реальное имя файла, которое он имел до отправки.
  • $_FILES['поле-запроса']['size'] — размер загруженного файла в байтах.
  • $_FILES['поле-запроса']['type'] — MIME-тип файла.
  • $_FILES['поле-запроса']['tmp_name'] — содержит имя файла, которое назначил ему интерпретатор при размещении во временную директорию;
  • $_FILES['поле-запроса']['error'] — код ошибки, возникшей при загрузке. Если всё нормально, элемент будет иметь значение «0».

Поле веб-формы может иметь атрибут multiple, позволяющий осуществлять множественный выбор файлов. В таком случае элементы name, size, type, tmp_name и error будут являться массивами. Например, загружены два файла через поле формы с именем test-file. Получить имя первого файла можно в $_FILES['test-file']['name'][0], а второго $_FILES['test-file']['name'][1].

Заметка
Существует одно требование к HTML-разметке полей, осуществляющих множественный выбор и загрузку файлов. Их атрибут name должен быть составлен следующим образом «name="имя-атрибута[]"». Если вы опустите конструкцию [], PHP обработает только один файл.

Перемещение загруженного файла

Как говорилось выше, загружаемые файлы размещаются во временной директории сервера и автоматически удаляются PHP-интерпретатором после выполнения текущего запроса. Их можно сохранить, переместив в другое место. Использовать стандартные функции copy() или rename() крайне нежелательно.

Для перемещения загруженных файлов существует специальная функция move_uploaded_file(). Она принимает два обязательных строковых параметра. Первый указывает имя файла во временной директории, а второй - путь назначения. Функция возвращает true в случае успеха и false, если произошла ошибка.

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

//Определяем место сохранения загруженного файла и его имя
$destination = $_SERVER['DOCUMENT_ROOT']. '/uploads';
$fileTempName = $_FILES['parameter']['tmp_name'];

if (is_uploaded_file($fileTempName)) {
    //Проверяем тип файла и меняем его имя в соответствии
    $newFilename = $destination .'/user';

    switch ($_FILES['parameter']['type']) {
        case 'application/pdf':
            $newFilename .= '-document.pdf';
            break;

        case 'video/mp4':
            $newFilename .= '-video.mp4';
            break;

        default:
            echo 'Файл неподдерживаемого типа';
            exit;
    }

    //Перемещаем файл из временной папки в указанную
    if (move_uploaded_file($fileTempName, $newFilename)) {
        echo 'Файл сохранен под именем '. $newFilename;

    } else {
        echo 'Не удалось осуществить сохранение файла';
    }
} else {
    echo 'Файл не был загружен на сервер';
}

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

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

Пример загрузки файла на сервер

Ниже приводится пример PHP-скрипта. Если он вызывается в первый раз, либо в текущем запросе отсутствует загрузка файла, пользователю выводится форма. При загрузке, файл перемещается в корневую директорию сайта, а пользователю показывается информация, связанная с ним. Обрабатываются только изображения в форматах jpg, jpeg и png.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Простая форма загрузки файла</title>
    </head>
    <body>
        <?php if (!isset($_FILES['upload']['tmp_name'])) : ?>
            <!-- Данная форма будет показана, если не было загрузок -->
            <form method="POST" enctype="multipart/form-data">
                <input name="upload" type="file">
                <br><br>
                <input type="submit" value="Отправить">
            </form>

        <?php else: ?>
            <?php
                $newFilename = $_SERVER['DOCUMENT_ROOT']. '/uploaded-file';
                $uploadInfo = $_FILES['upload'];

                //Проверяем тип загруженного файла и дописываем расширение
                switch ($uploadInfo['type']) {
                    case 'image/jpeg':
                        $newFilename .= '.jpg';
                        break;

                    case 'image/png':
                        $newFilename .= '.png';
                        break;

                    default:
                        echo 'Файл неподдерживаемого типа';
                        exit;
                }

                //Перемещаем файл из временной папки в указанную
                if (!move_uploaded_file($uploadInfo['tmp_name'], $newFilename)) {
                    echo 'Не удалось осуществить сохранение файла';
                }
            ?>

            <!-- Выводим разметку, содержащую информацию о файле -->
            <img src="/<?php echo basename($newFilename) ?>">
            <ul>
                <li>Размер файла: <?php echo $uploadInfo['size'] ?>байт</li>
                <li>Имя до загрузки: <?php echo $uploadInfo['name'] ?></li>
                <li>MIME-тип: <?php echo $uploadInfo['type'] ?></li>
            </ul>
        <?php endif; ?>
    </body>
</html>

Последние публикации