在PHP中使用regex过滤掉有效的文件名

时间:2014-01-02 10:24:42

标签: php regex preg-match

我有一个PHP网站,注册用户可以上传头像。其中一个限制是,人们只能上传只包含字母数字字符的.jpg或.jpeg文件,其他任何内容都会被拒绝。这是为了确保我只上传像“avatar.jpg”,而不是“evilcode.php”或“secretcode.php.jpg”。我还计划进行其他检查,但现在我无法完成第一步。

我正在使用这个正则表达式:

[a-zA-Z0-9]{1,150}+\.+(jpe?g)

这是我目前正在使用的代码。该函数从另一个php文件调用,$ _FILES ['avatar']作为参数。

public function updateAvatar($avatar)
{
    $regex = '^[a-zA-Z0-9]{1,100}+\.+(jpe?g)$';
    $name = $avatar['name'];    
    $result = preg_match_all($regex, $name);
    if($result === 1)
    {
        return true;
    } else
    {
        return false;
    }
}

当上传“avatar.jpg”,“code.php”或“duck.gif”时,这总是返回false。根据PHP手册,这段代码应该是正确的。该方法返回一个整数或一个布尔值,并警告您应该使用===,而不是==来比较结果。有谁知道我做错了什么?

5 个答案:

答案 0 :(得分:2)

当您通过正则表达式检查传入文件时,可以使用可执行的mime上传exploit file,因此您必须检查文件的mime以便安全上传:

public function updateAvatar($avatar)
{
    $available_mimes = array(
        'jpeg' => 'image/jpeg',
        'jpg' => 'image/jpg',
        'iejpg' => 'image/pjpeg' // this mime sent Internet Explorer for jpg files
    );

    if(in_array($avatar['type'], $available_mimes)
    {
        return true;
    }
    else
    {
        return false;
    }
}

关于你的正则表达式函数:

public function updateAvatar($avatar)
{
    // Use regex with ignore case flag (for validating jpg and JPG)

    // Uncomment next line, if you want to check files with "_" symbols at name
    // if(preg_match('/^(\w+)\.(jpe?g)$/i', $avatar['name']))

    if(preg_match('/^([a-z0-9]+)\.(jpe?g)$/i', $avatar['name']))
    {
        return true;
    } 
    else
    {
        return false;
    }
}

尝试使用preg_match()

答案 1 :(得分:1)

你的正则表达式没有分隔符:

/^[a-zA-Z0-9]{1,100}+\.+(jpe?g)$/

并且在检查单个头像文件名时不需要preg_match_all()

public function updateAvatar($avatar)
{
    $regex = '/^[a-zA-Z0-9]{1,100}+\.+(jpe?g)$/';
    $name = $avatar['name'];    
    if(preg_match($regex, $name))
        return true;
    return false;
}

但是你最好将你的正则表达式更改为:

/^[a-zA-Z0-9]{1,100}\.(jpe?g)$/

在不需要量词后的+符号,您也不应该在名称末尾验证多个dot作为您的要求。

Live demo

答案 2 :(得分:0)

我看到两个问题。首先,PHP的RegEx函数期望模式被您选择的分隔符字符包围(正则表达式选项位于结束分隔符之后)。

例如:$regex = '/^[a-zA-Z0-9]{1,100}+\.+(jpe?g)$/';$regex = '|^[a-zA-Z0-9]{1,100}+\.+(jpe?g)$|';

其次,您同时使用{1,100}(“指定类的一到100个字符串”)以及+(“指定类的一个或多个字符”)。只使用其中一种。

答案 3 :(得分:0)

尝试使用此,

/\.(jpg|jpeg|png|gif)(?:[\?\#].*)?$/i

答案 4 :(得分:-1)

在你的正则表达式中添加分隔符,试试这个:

$regex = '/^[a-zA-Z0-9]{1,100}+\.+(jpe?g)$/';
//        ^                               ^