Подтвердить что ты не робот

Какой лучший способ создать форму загрузки одного файла с помощью PHP?

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

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

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

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

4b9b3361

Ответ 1

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

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

<?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 "</pre>";
?>

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

Печать значения $_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 Указывает, что максимальный размер файла, определенный вручную, на странице script был превышен
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.

Проверка типов файлов

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

Ответ 2

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

Ответ 3

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

Ответ 4

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

.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