PHP - цикл по $ _FILES для проверки типа файла - PullRequest
7 голосов
/ 17 июля 2009

Мой первый вопрос о ТАК, спасибо. :)

Я разрабатываю систему регистрации проблем поддержки для своей компании, и она должна разрешать загрузку файлов, а также любые проблемы, отправленные в нашу базу данных. Может быть от 0 до 6 различных загрузок, чтобы проверить, наряду с проблемой поддержки. Мне удалось получить точную переменную количества файлов благодаря наличию скрытого поля ввода (imgcount), которое обновляется через js всякий раз, когда изображение выбирается с помощью ввода type = "file" или удаляется из формы.

Мои [input type = "file"] имена - это image1, image2 и т. Д. Как я и думал, проще было бы проходить через них.

Когда форма отправлена, следующий код проверяет наличие файлов и проверяет их допустимый тип (gif / jpeg / png), чтобы их можно было безопасно загрузить. Я не слишком беспокоюсь о вирусах, поскольку система поддержки имеет хороший безопасный вход в систему, и мы доверяем нашим клиентам.

$sscount = $_POST['imgcount'];
echo $sscount; //to test the variable
if($sscount>0){
    for($i = 1; $i <= $sscount; $i++){
        if (($_FILES["image$i"]["type"] == "image/gif")
        || ($_FILES["image$i"]["type"] == "image/jpeg")
        || ($_FILES["image$i"]["type"] == "image/png" )
        && ($_FILES["image$i"]["size"] < 500000))
        {

        }
        else
        {
        $errormsg .= "Error: Image $i must be either JPEG, GIF, or PNG and less than 500 kb.<br />";
        }
    }
}

Но это, кажется, не проходит правильно, у кого-нибудь есть идеи, как я могу заставить его пройти и правильно вернуться?

Ответы [ 7 ]

9 голосов
/ 17 июля 2009

Оператор && имеет более высокий приоритет , чем ||, поэтому вместо (A OR B OR C) AND D, как вы и предполагали, на самом деле это A OR B OR (C AND D)

Вы можете использовать скобки, чтобы обеспечить оценку, которую вы намеревались.

Однако что-то вроде этого может быть чище и проще в обслуживании / чтении:

$allowed_types=array(
    'image/gif',
    'image/jpeg',
    'image/png',
);


$sscount = $_POST['imgcount'];
if($sscount>0){
    for($i = 1; $i <= $sscount; $i++){

        if (in_array($_FILES["image$i"]["type"], $allowed_types) && 
            ($_FILES["image$i"]["size"] < 500000))
        {

        }

    }
}
5 голосов
/ 17 июля 2009

Это не прямой ответ на ваш вопрос, но вы можете передавать значения форм в PHP в виде массива, который должен быть легче проходить. in_array() также полезно для проверки того, что значение находится в допустимом списке.

HTML:

<input type="file" name="image[]">
<input type="file" name="image[]">
<input type="file" name="image[]">
<input type="file" name="image[]">

PHP:

<?php
if (isset($_FILES['image'])) {
    foreach ($_FILES['image'] as $file) {
        if (!in_array($file['type'], array("image/gif", "image/jpeg", "image/png"))
           || $file['size'] > 500000) {
           //error
        } else {
           //ok
        }
    }
}
4 голосов
/ 17 июля 2009

Как уже упоминали другие, способ, которым вы сгруппировали свои условные выражения, был неправильным. Однако вместо того, чтобы просто добавить несколько скобок, я бы посоветовал вам полностью отделить два условия;

// this declaration + the use of in_array() isn't necessary,
// it just makes things a bit cleaner.
$file_types = array("image/gif","image/jpeg","image/png"); 

if($_FILES["image$i"]["size"] < 500000)
{
    if(in_array($_FILES["image$i"]["type"], $file_types)))
    {
        // do stuff
    }
    else
    {
        // error about file type
    }
}
else
{
    // error about file size
}

Наличие этого разделения делает код более читабельным и предлагает иерархию условий с большей готовностью, плюс он делает ваши сообщения об ошибках более значимыми Рекомендуется разделять условные операторы разных типов, чтобы любые сообщения об ошибках оставались полезными. Если ваш код выдал ошибку как есть, у пользователя нет возможности узнать (без необходимости бредить себя), было ли его изображение слишком большим или неправильного типа.

2 голосов
/ 17 июля 2009

Не думаю, что вам действительно нужна переменная, которая обновляется через Javascript. Вы можете использовать PHP, чтобы определить, сколько файлов было загружено , проверяя код ошибки . Вы можете обработать загрузку файлов, также проверив расширение файла, так как разные браузеры часто могут отправлять разные типы MIME. Вот пример того, о чем я говорю:

$accepted_files = array(
    'jpg',
    'png',
    'gif',
    'jpeg'
);

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    foreach($_FILES as $key => $upload) {
        if ($upload['error'] == 0) {
            $file_parts = explode ('.',$upload['name']);
            if (in_array($file_parts[sizeof($file_parts)-1], $accepted_files)) {
                // This type of file is a-ok
            }
            else {
                // Not an accepted file type
            }
        }
    }
}   
2 голосов
/ 17 июля 2009

Ну, ваша логическая логика неоднозначна и, вероятно, не делает то, что вы хотите. Это, вероятно, будет работать лучше:

    if ((($_FILES["image$i"]["type"] == "image/gif")
    || ($_FILES["image$i"]["type"] == "image/jpeg")
    || ($_FILES["image$i"]["type"] == "image/png" ))
    && ($_FILES["image$i"]["size"] < 500000))

Хотя, если бы у меня были мои барабанщики, все это выглядело бы так:

    $file = $_FILES['image' . $i];
    $type = $file['type'];
    if(($type == 'image/gif' || $type == 'image/jpeg' || $type == 'image/png') && $file['size'] < 500000)
0 голосов
/ 17 июля 2009

Вы можете объединить все ['type'] == x || ['type'] == y за один вызов in_array ($ _ FILES [...] ['type'], $ позволено)>

$ _ FILES [..] ['type'] содержит данные, отправленные клиентом, которые не проверяются и не обрабатываются php. Если тип файла имеет какое-либо значение, не полагайтесь на $ _FILES [..] ['type'] или суффикс $ _FILES [..] ['name']. Только фактическое содержание имеет значение. При необходимости вы можете проверить это с расширением fileinfo или mime_content_type () (которое помечено как устаревшее в пользу fileinfo)

0 голосов
/ 17 июля 2009

Я думаю, что ваше if условно неверно. Вам нужны скобки вокруг первой группы логических значений, которые OR, как это:

   if ( (($_FILES["image$i"]["type"] == "image/gif")
    || ($_FILES["image$i"]["type"] == "image/jpeg")
    || ($_FILES["image$i"]["type"] == "image/png" ))
    && ($_FILES["image$i"]["size"] < 500000))

Это правильно означает, что «если файл является изображением (gif или jpeg или png) И меньше этого размера».

То, как вы это делали раньше, вряд ли было той логикой, которую вы хотели.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...