允许特定文件类型? php上传

时间:2011-09-30 23:18:43

标签: php html

我创建了一个图像上传器,我不知道怎么做,只有文件类型可以是.jpg所以我问你,你知道吗?

到目前为止我得到了什么:

    <?php
session_start();
if($_SESSION['username']) {
    $target_path = "users/$username/";

    $target_path = $target_path . basename( $_FILES['uploadedfile']['name']); 

    if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
        echo "The file ".  basename( $_FILES['uploadedfile']['name']). 
        "has been uploaded";
        header("Location: user.php");
    } else{
        echo "There was an error uploading the file, please try again!";
    }
}
    else {
            echo "Only members can be here. Register <a href='index.php'>here</a>";
  }
  ?>

还有一件事,我怎样才能将上传的文件重命名为:“profile.jpg”?

6 个答案:

答案 0 :(得分:2)

jpeg幻数是0xffd8所以你可以检查文件的前两个字节是0xff和0xd8,如果它们不是那么它肯定不是jpeg。

示例:

$fp = fopen($_FILES['uploadedfile']['tmp_name'], 'rb');
$bytes = fread($fp, 2);

if (ord($bytes{0}) != 0xff && ord($bytes{1}) != 0xd8) {
    echo "Not JPEG!";
} else {
    echo "It is JPEG";
}

一个真正恶意的用户会试图通过完全绕过你的表单来上传文件,这样他们就可以上传任何类型的文件,即使它不是.jpg,也可以发送图片/ jpg | jpeg mime键入即使这不是正确的mime类型,因为浏览器只是将该mime类型作为服务发送给您,但它不能被信任。

答案 1 :(得分:2)

这里有一些重要的事情需要考虑:

首先,永远不要依赖提供的文件扩展名。如果需要,我可以上传一个扩展名为.jpg的php文件。当然,我可能需要做更多的事情来实际让它作为服务器上的php文件执行,但它肯定不是一个有效的图像。

如果上传成功,$_FILES[ 'uploadedfile' ][ 'type' ]将保留请求提供的mime类型。但是,这也应该不值得信任,因为它也可以被篡改。

确定上传文件实际上是jpeg类型图像的更可靠方法是使用函数getimagesize。如果getimagesize()不是有效图像,则会返回false,如果将文件识别为图像,则返回包含图像信息的数组。数组的索引2将包含与以IMAGETYPE_开头的one of these constants对应的值。

$info = getimagesize( $_FILES[ 'uploadedfile' ]['tmp_name'] );
if( $info !== false )
{
    // file is an image to begin with

    if( $info[ 2 ] == IMAGETYPE_JPEG )
    {
        // file appears to be a valid jpeg image
    }
}

这有点像一种老式的方法,据我所知,虽然可靠。

我相信,根据平台(Windows / * nix)和版本(&lt; 5.3,&gt; = 5.3),有更可靠的方法来确定文件的实际mime类型。我会在稍后看到我能为你找到的东西。

修改
我忘记了重命名部分。

只需替换它:

$target_path = $target_path . basename( $_FILES['uploadedfile']['name']);

......用这个:

$target_path = $target_path . 'profile.jpg';

换句话说,当您使用move_uploaded_file()移动文件时,第二个参数将是新路径(包括新文件名)。

答案 2 :(得分:1)

HTML5的accept属性允许您指定输入可接受的文件类型:

<input type="file" accept="image/jpeg" />

这意味着出现的文件选择对话框只允许您选择jpeg。我不知道浏览器支持的程度如何。

修改:我也不知道浏览器将如何执行此检查。如果你真的想要强制执行仅限jpeg的政策,那么你需要像@ drew010所提议的那样。

答案 3 :(得分:1)

您可以使用getimagesize()来验证图片的格式。

但是,保护文件上传非常复杂,还需要执行其他步骤。例如,使用用户提供的原始文件名是危险的。

请参阅此问题,以获得有关为实现真正高级别安全性而可能/需要执行的操作的高级讨论:

PHP image upload security approach

答案 4 :(得分:1)

根据您想要达到的安全级别,您可以执行不同的检查以仅允许JPG图像。

简单地说,您可以检查* jpg扩展名,但这很天真,就像重命名文件一样,它会欺骗您的代码。 另一种方法是检查MIME类型(jpeg或pjpeg),它是$ _FILES数组的一部分

$_FILES['uploadedfile']['type']

但是这些信息不可靠,可能会被欺骗。

但我想到的最好的解决方案是使用函数getimagesize()来分析图像,你可以获得几个信息,最重要的是验证文件是实际上是真实的形象。 此函数返回包含7个元素的数组。

Index 0 and 1 contains the width and the height of the image.
Index 2 is one of the IMAGETYPE_XXX constants indicating the type of the image.

Index 3 is a text string with the correct height="yyy" width="xxx" string 
*mime* is the correspondant MIME type of the image.
*channels* will be 3 for RGB pictures and 4 for CMYK pictures.
*bits* is the number of bits for each color.  

上述信息来自手册页。

答案 5 :(得分:1)

你可以做很多事情,让图片上传更安全:

  • 将图像调整为标准尺寸。这可以确保上传图片中的恶意代码会被加扰。
  • 将上传的图片重命名为统一的名称架构,这使得请求准备好的文件变得更加困难,并且可以确保正确的文件扩展名。
  • 在.htaccess文件中进行一些设置,因此只会从图片目录中传送jpg文件。

这是一个如何编写.htaccess文件的例子:

IndexIgnore *
Deny from all

<FilesMatch "\.(jpg|jpeg)$">
    Allow from all
</FilesMatch>

这些是我认为重要的一些要点,但这份清单当然不具有吸引力。