You do not need fopen
to use getimagesize
, actually fopen
will keep the file open until the script finishes, which is really a problem, for example if you are going to do delete or edit operations or change the pointer position.
Another unnecessary check that can lead to error is the file extension check, it really is somewhat unnecessary if you take into account that a server can customize the extensions, even if the internal content of the document is an image .
It would be best to only use is_file
combined with getimagesize
, since it will only recognize images, like this:
function is_image($path)
{
return is_file($path) && getimagesize($path) !== false;
}
The is_file
checks if it is a file and if it exists, if it is a folder or does not exist it returns false
.
The getimagesize
always returns array, except when the file is not an image, so in the !== false
case it may be a bit better in micro-optimization, for example you will check several files at once for a folder, where may contain thousands of files.
If you want to check specific, instead of using getimagesize
it might be more efficient to use finfo
, which uses MAGIC to check the mime-type of the file, for example:
class Image
{
const JPEG = 1;
const GIF = 2;
const PNG = 3;
const WEBP = 4;
const SVG = 5;
public static function isImage($path, $type)
{
if (is_file($path) === false) {
return false;
}
$mime = self::mime($path);
switch ($type) {
case self::JPEG:
return $mime === 'jpeg';
case self::GIF:
return $mime === 'gif';
case self::PNG:
return $mime === 'png';
case self::WEBP:
return $mime === 'webp';
case self::SVG:
return $mime === 'svg+xml';
default:
throw new InvalidArgumentException("Argumento precisa ser uma das constantes definidas na class Image");
}
}
private static function mime($path)
{
$mime = '';
if (function_exists('finfo_open')) {
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $path);
finfo_close($finfo);
} elseif (function_exists('mime_content_type')) {
$mime = mime_content_type($path);
}
return strpos($mime, 'image/') === 0 ? substr($mime, 6) : false;
}
}
The usage would look pretty simple, like this:
Image::isImage('image/foto.jpg', Image::JPEG); //Retorna TRUE
Image::isImage('image/foto.jpg', Image::GIF); //Retorna FALSE
Image::isImage('image/foto.jpg', Image::PNG); //Retorna FALSE
In a procedural style you could do this:
define('IMAGE_JPEG', 1);
define('IMAGE_GIF', 2);
define('IMAGE_PNG', 3);
define('IMAGE_WEBP', 4);
define('IMAGE_SVG', 5);
function is_image($path, $type)
{
if (is_file($path) === false) {
return false;
}
$mime = image_mime($path);
switch ($type) {
case IMAGE_JPEG:
return $mime === 'jpeg';
case IMAGE_GIF:
return $mime === 'gif';
case IMAGE_PNG:
return $mime === 'png';
case IMAGE_WEBP:
return $mime === 'webp';
case IMAGE_SVG:
return $mime === 'svg+xml';
default:
throw new InvalidArgumentException("Argumento precisa ser uma das constantes definidas na class Image");
}
}
function image_mime($path)
{
$mime = '';
if (function_exists('finfo_open')) {
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $path);
finfo_close($finfo);
} elseif (function_exists('mime_content_type')) {
$mime = mime_content_type($path);
}
return strpos($mime, 'image/') === 0 ? substr($mime, 6) : false;
}
The usage would look like this:
is_image('image/foto.png', IMAGE_JPEG); //Retorna FALSE
is_image('image/foto.png', IMAGE_GIF); //Retorna FALSE
is_image('image/foto.png', IMAGE_PNG); //Retorna TRUE