在PHP中获取照片文件扩展名的最佳方法

3
我正在重新构建我的网站上的照片上传部分,我正在尽可能学习更多知识,以便既能确保安全性,又能实现最佳性能。通常情况下,我的网站每分钟上传大约15-20张照片。
那么,这种方法是否可靠来获取照片的文件类型,比如jpg、gif、png?
 $fileType = $_FILES['image']['type'];

1
image_type_to_extension(exif_imagetype('your_file_name')); 将输出您的文件的 '.extension' (例如:'.png'、'.jpeg')即使它不是文件名中的一部分,因为 exif_imagetype() 从文件开头读取类型。 - fider
4个回答

13
文件扩展名有时会误导人,或者至少可以这么说。最好不要依赖/信任用户提交的数据。正如PHP手册所指出的: $_FILES['userfile']['type'] - 如果浏览器提供了该信息,则为文件的MIME类型。例如:"image/gif"。但是,PHP端不会检查此MIME类型,因此不要对其值抱有期望。
这是不可靠的。
以下是更好的方法:
PHP的getimagesize()函数返回一个按数字索引的数组,其中包含有关图像的数据,索引2是IMAGETYPE_XXX常量之一(完整列表可在此处查看),指示图像的类型。然后,这些常量可以在许多GD系列函数中使用,其中两个相关的函数是image_type_to_extension()image_type_to_mime_type()
因此,您可以轻松地按照以下方式进行操作:
$imageData = getimagesize($_FILES['userfile']['tmp_name']);
// $imageData[2] will contain the value of one of the constants
$mimeType = image_type_to_mime_type($imageData[2]);
$extension = image_type_to_extension($imageData[2]);

虽然,如果您有可用的exif扩展,[exif_imagetype()][5]函数将返回与getimagesize()的索引2相同的结果,但速度更快。
我以GD方法作为主要示例,因为它们在PHP安装中更常见。但是,Imagick扩展也提供类似的功能,您还可以使用fileinfo扩展验证MIME类型(自5.3版本起已包含)。

+1,哎呀,你比我快了。getimagesize是我会用的。 - karim79
image_type_to_extension函数:“此函数不需要GD图像库。” - qwertzman

2

exif_imagetype是检查一个文件是否为有效图像文件的最安全、最快速和最可靠的方式,它还可以处理远程URL。

返回值与getimagesize()在索引2中返回的值相同,但exif_imagetype()更快。

$type = @exif_imagetype($_FILES['image']['tmp_name']);

if (($type >= 1) && ($type <= 3))
{
    echo 'Valid image (GIF, JPG or PNG).';
}

else
{
    unlink($_FILES['image']['tmp_name']); // delete it
}

2

首先尝试使用getimagesizeexif_imagetype()

如果它们没有返回['mime'],则尝试使用finfo_file(如果已加载extension_loaded('fileinfo')),

如果仍然没有结果,则尝试使用mime_content_type(如果function_exists('mime_content_type'))。

如果您不需要MIME类型,而只需要文件扩展名,请使用pathinfo($path, PATHINFO_EXTENSION)


使用pathinfo($path, PATHINFO_EXTENSION)。用户是否可以将php文件命名为jpg扩展名,使系统认为它是一个jpg文件? - JasonDavis

1

文档所述,

文件的 MIME 类型(如果浏览器提供此信息)[...] 然而,在 PHP 方面并未检查此 MIME 类型,因此不要轻信它的值

换句话说,您不应该信任它,因为我可以上传任何我想要的内容,并使它看起来像是一张 jpeg 图像。

为确保上传的文件实际上是一张图像,我过去个人使用了Imagick::identifyImage,结果非常好。GD 可能也有类似的函数。

或者您可以使用文件信息扩展名在服务器端获取 MIME 类型,特别是finfo_file()


+1因为在可能的情况下应始终使用Imagick函数而不是GD函数,因为它们更具性能。 - karim79

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接