Каков наилучший способ создания формы загрузки одного файла с использованием PHP? - PullRequest
21 голосов
/ 13 октября 2008

Я нашел несколько примеров в Интернете, но я хотел бы получить отзывы от людей, ежедневно использующих PHP, в отношении потенциальных соображений безопасности или производительности и их решений.

Обратите внимание, что меня интересует загрузка только одного файла за раз.

В идеале плагин для браузера не требуется (Flash / Java), хотя было бы интересно узнать о преимуществах использования плагина.

Я хотел бы знать как лучший код формы HTML, так и код обработки PHP.

Ответы [ 4 ]

33 голосов
/ 13 октября 2008

Учебник по загрузке файлов

HTML

<form enctype="multipart/form-data" action="action.php" method="POST">
  <input type="hidden" name="MAX_FILE_SIZE" value="1000000" />
  <input name="userfile" type="file" />
  <input type="submit" value="Go" />
</form>
  • action.php - это имя файла PHP, который будет обрабатывать загрузку (показано ниже)
  • MAX_FILE_SIZE должен появиться непосредственно перед вводом типа file. Этим значением можно легко манипулировать на клиенте, поэтому на него не следует полагаться. Его основное преимущество заключается в предоставлении пользователю заблаговременного предупреждения о том, что его файл слишком велик, прежде чем он загрузит его.
  • Вы можете изменить имя ввода с помощью типа file, но убедитесь, что оно не содержит пробелов. Вы также должны обновить соответствующее значение в файле PHP (ниже).

PHP

<code><?php
$uploaddir = "/www/uploads/";
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);

echo '<pre>';
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
    echo "Success.\n";
} else {
    echo "Failure.\n";
}

echo 'Here is some more debugging info:';
print_r($_FILES);
print "
"; ?>

Папка для загрузки не должна находиться в месте, доступном по HTTP, иначе можно было бы загрузить скрипт PHP и выполнить его на сервере.

Печать значения $_FILES может дать подсказку о том, что происходит. Например:

    Array
    (
        [userfile] => Array
        (
            [name] => Filename.ext
            [type] => 
            [tmp_name] => 
            [error] => 2
            [size] => 0
        )
    )

Эта структура дает некоторую информацию относительно имени файла, типа MIME, размера и кода ошибки.

Коды ошибок

0 Указывает, что ошибок не было и файл был успешно загружен
1 Указывает, что размер файла превышает максимальный размер файла, определенный в php.ini. Если вы хотите изменить максимальный размер файла, вам нужно открыть файл php.ini, определить строку, которая гласит: upload_max_filesize = 2M, и измените значение с 2M (2MB) на то, что вам нужно
2 Указывает, что максимальный размер файла, определенный вручную в сценарии на странице, был превышен
3 Указывает, что файл был загружен только частично
4 Указывает, что файл не был указан (пустое поле файла)
5 Пока не определено
6 Указывает, что нет временной папки
7 Указывает, что файл не может быть записан на диск

php.ini Конфигурация

При запуске этой установки с большими файлами вы можете получить ошибки. Проверьте файл php.ini на наличие этих ключей:

max_execution_time = 30
upload_max_filesize = 2M

Увеличение этих значений по мере необходимости может помочь. При использовании Apache изменения в этом файле требуют перезагрузки.

Максимально допустимое значение памяти (установленное с помощью memory_limit) здесь не играет роли, поскольку файл записывается в каталог tmp по мере его загрузки. Расположение каталога tmp опционально контролируется с помощью upload_tmp_dir.

Проверка файла mimetypes

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

Вы можете использовать очень полезное расширение fileinfo (которое заменяет более старую mime_content_type функцию) для проверки типов mime.

// FILEINFO_MIME set to return MIME types, will return string of info otherwise
$fileinfo = new finfo(FILEINFO_MIME);
$file = $fileinfo->file($_FILE['filename']);

$allowed_types = array('image/jpeg', 'image/png');
if(!in_array($file, $allowed_types))
{
    die('Files of type' . $file . ' are not allowed to be uploaded.');
}
// Continue

Дополнительная информация

Подробнее об обработке загрузки вы можете прочитать в руководстве по PHP.net .

Для PHP 5.3 +

//For those who are using PHP 5.3, the code varies.
$fileinfo = new finfo(FILEINFO_MIME_TYPE);
$file = $fileinfo->file($_FILE['filename']['tmp_name']);
$allowed_types = array('image/jpeg', 'image/png');
if(!in_array($file, $allowed_types))
{
    die('Files of type' . $file . ' are not allowed to be uploaded.');
}
// Continue

Дополнительная информация

Подробнее о FILEINFO_MIME_TYPE можно прочитать в документации по PHP.net .

5 голосов
/ 13 октября 2008

Прочитайте это введение , которое должно рассказать вам все, что вам нужно знать. Комментарии пользователей также весьма полезны.

4 голосов
/ 13 октября 2008

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

3 голосов
/ 14 октября 2008

Безопасность - довольно большая вещь для загрузки файлов, добавление .htaccess в папку загрузки, которая останавливает запуск сценариев, может быть полезным для добавления дополнительного уровня безопасности.

.htaccess

Options -Indexes
Options -ExecCGI
AddHandler cgi-script .php .php3 .php4 .phtml .pl .py .jsp .asp .htm .shtml .sh .cgi 

Ссылка: http://www.mysql -apache-php.com / fileupload-security.htm

...