najlepszy sposób na określenie, czy adres URL jest obrazem w PHP
Używając PHP, podanego adresu URL, jak Mogę określić, czy jest to obraz?
Nie ma kontekstu dla adresu URL - jest on po prostu w środku zwykłego pliku tekstowego, a może po prostu ciągiem znaków.
Nie chcę wysokich kosztów (np. czytania zawartości adresu URL) , ponieważ może to być wywołane dla wielu adresów URL na stronie. Biorąc pod uwagę to ograniczenie, nie jest istotne, aby wszystkie obrazy były identyfikowane, ale chciałbym dość dobrego zgadywania.
W tej chwili patrzę właśnie na rozszerzenie pliku, ale wydaje mi się, że powinien być lepszy sposób niż ten.
Oto co aktualnie mam:
function isImage( $url )
{
$pos = strrpos( $url, ".");
if ($pos === false)
return false;
$ext = strtolower(trim(substr( $url, $pos)));
$imgExts = array(".gif", ".jpg", ".jpeg", ".png", ".tiff", ".tif"); // this is far from complete but that's always going to be the case...
if ( in_array($ext, $imgExts) )
return true;
return false;
}
Edit: w przypadku, gdy jest to przydatne dla kogokolwiek innego tutaj jest ostateczna funkcja przy użyciu techniki z odpowiedzi Emila H:
function isImage($url)
{
$params = array('http' => array(
'method' => 'HEAD'
));
$ctx = stream_context_create($params);
$fp = @fopen($url, 'rb', false, $ctx);
if (!$fp)
return false; // Problem with url
$meta = stream_get_meta_data($fp);
if ($meta === false)
{
fclose($fp);
return false; // Problem reading data from url
}
$wrapper_data = $meta["wrapper_data"];
if(is_array($wrapper_data)){
foreach(array_keys($wrapper_data) as $hh){
if (substr($wrapper_data[$hh], 0, 19) == "Content-Type: image") // strlen("Content-Type: image") == 19
{
fclose($fp);
return true;
}
}
}
fclose($fp);
return false;
}
8 answers
Możesz użyć żądania HTTP HEAD i sprawdzić typ zawartości. To może być dobry kompromis. Można to zrobić za pomocą strumieni PHP. Wez Furlong ma Artykuł, który pokazuje, jak używać tego podejścia do wysyłania żądań post, ale można go łatwo dostosować do wysyłania żądań HEAD. Możesz pobrać nagłówki z odpowiedzi http za pomocą stream_get_meta_data().
Oczywiście to nie jest naprawdę 100%. Niektóre serwery wysyłają nieprawidłowe nagłówki. Będzie jednak obsługa przypadków, w których obrazy są dostarczane za pośrednictwem skryptu, a prawidłowe rozszerzenie pliku nie jest dostępne. Jedynym sposobem, aby być naprawdę pewnym, jest odzyskanie obrazu - albo całego, albo kilku pierwszych bajtów, jak zasugerował thomasrutter.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-24 11:31:32
Istnieje kilka różnych podejść.
-
Powąchaj zawartość, szukając magicznej liczby na początku pliku. Na przykład GIF używa GIF87 lub GIF89 jako pierwszych pięciu bajtów pliku (w ascii). Niestety nie można stwierdzić, czy obraz zawiera błąd lub czy zawiera złośliwą zawartość. Oto kilka magicznych liczb dla różnych typów plików graficznych (możesz ich używać):
"\xff\xd8\xff" => 'image/jpeg', "\x89PNG\x0d\x0a\x1a\x0a" => 'image/png', "II*\x00" => 'image/tiff', "MM\x00*" => 'image/tiff', "\x00\x00\x01\x00" => 'image/ico', "\x00\x00\x02\x00" => 'image/ico', "GIF89a" => 'image/gif', "GIF87a" => 'image/gif', "BM" => 'image/bmp',
Wąchanie takiej treści prawdopodobnie będzie najlepiej dopasuj się do swoich wymagań; będziesz musiał tylko przeczytać i dlatego pobrać kilka pierwszych bajtów pliku(obok nagłówka).
Załaduj obraz za pomocą biblioteki GD, aby sprawdzić, czy ładuje się bez błędów. Dzięki temu dowiesz się, czy obraz jest poprawny, bez błędu, czy nie. Niestety to prawdopodobnie nie spełnia twoich wymagań, ponieważ wymaga pobrania pełnego obrazu.
- Jeśli naprawdę nie chcesz w ogóle wysyłać żądania HTTP dla obrazu, to wyklucza to zarówno sniffing jak i getting HTTP headers. Możesz jednak spróbować określić, czy coś jest obrazem po kontekście, w którym jest powiązane. Coś związanego za pomocą atrybutu src w elemencie
Niestety, możliwe jest, że plik może być zarówno poprawnym obrazem, jak i plikiem ZIP zawierającym szkodliwe treści, które mogą być uruchamiane jako Java przez szkodliwą stronę - zobacz exploit GIFAR. Możesz prawie na pewno zapobiec tej luce, ładując obraz w bibliotece takiej jak GD i wykonując na nim jakiś nietrywialny filtr, taki jak zmiękczenie lub wyostrzenie go w niewielkiej ilości (np. używając filtra splotowego) i zapisując go do świeżego pliku bez przenoszenia jakichkolwiek metadanych.
Próba określenia, czy coś jest obrazem przez sam typ zawartości, jest dość zawodna, prawie tak samo zawodna jak sprawdzanie rozszerzenia pliku. Podczas ładowania obrazu za pomocą elementu
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-24 11:31:07
if(is_array(getimagesize($urlImg)))
echo 'Yes it's an image!';
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-06 14:27:43
Oprócz odpowiedzi Emila H:
Użycie get_headers()
do sprawdzenia typu zawartości url bez pobierania całego pliku za pomocą getimagesize()
$url_headers=get_headers($url, 1);
if(isset($url_headers['Content-Type'])){
$type=strtolower($url_headers['Content-Type']);
$valid_image_type=array();
$valid_image_type['image/png']='';
$valid_image_type['image/jpg']='';
$valid_image_type['image/jpeg']='';
$valid_image_type['image/jpe']='';
$valid_image_type['image/gif']='';
$valid_image_type['image/tif']='';
$valid_image_type['image/tiff']='';
$valid_image_type['image/svg']='';
$valid_image_type['image/ico']='';
$valid_image_type['image/icon']='';
$valid_image_type['image/x-icon']='';
if(isset($valid_image_type[$type])){
//do something
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-24 14:48:03
Edit: dla obrazów statycznych z popularnym rozszerzeniem obrazu.
<?php
$imgExts = array("gif", "jpg", "jpeg", "png", "tiff", "tif");
$url ='path/to/image.png';
$urlExt = pathinfo($url, PATHINFO_EXTENSION);
if (in_array($urlExt, $imgExts)) {
echo 'Yes, '.$url.' is an Image';
}
?>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-17 20:09:13
Podobne do niektórych udzielonych odpowiedzi, ale z nieco inną logiką.
$headers = @get_headers($url, 1); // @ to suppress errors. Remove when debugging.
if (isset($headers['Content-Type'])) {
if (strpos($headers['Content-Type'], 'image/') === FALSE) {
// Not a regular image (including a 404).
}
else {
// It's an image!
}
}
else {
// No 'Content-Type' returned.
}
@ jest operatorem kontroli błędów .
Uwaga użyliśmy operatora "strict" === FALSE
w warunku, ponieważ strpos($headers['Content-Type'], 'image/')
zwraca 0
w naszym przypadku użycia, jeśli igła znajduje się w stogu siana. Z odlewaniem typu przy użyciu ==
, które błędnie interpretuje się jako FALSE
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-14 00:28:24
Możemy użyć exif_imagetype do sprawdzenia typu obrazu, więc nie jest to dozwolone dla innych typów zawartości. Zezwala tylko na obrazy i możemy ograniczyć je do kilku typów obrazów, poniższy przykładowy kod pokazuje, jak zezwolić na typ obrazu GIF.
if (exif_imagetype('image.gif') != IMAGETYPE_GIF) {
echo 'The picture is not a gif';
}
Możesz użyć następujących typów obrazów,
IMAGETYPE_GIF
IMAGETYPE_JPEG
IMAGETYPE_PNG
IMAGETYPE_SWF
IMAGETYPE_PSD
IMAGETYPE_BMP
IMAGETYPE_TIFF_II (intel byte order)
IMAGETYPE_TIFF_MM (motorola byte order)
IMAGETYPE_JPC
IMAGETYPE_JP2
IMAGETYPE_JPX
IMAGETYPE_JB2
IMAGETYPE_SWC
IMAGETYPE_IFF
IMAGETYPE_WBMP
IMAGETYPE_XBM
IMAGETYPE_ICO
Więcej Szczegółów : link
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-29 05:47:05
Szybkie rozwiązanie dla uszkodzonych lub nie znalezionych obrazów link
polecam, że nie używaj getimagesize (), ponieważ będzie 1st pobrać obraz, a następnie sprawdzi rozmiar obrazków+jeśli to nie Obraz, to wyrzuci wyjątek, więc użyj poniższego kodu
if(checkRemoteFile($imgurl))
{
//found url, its mean
echo "this is image";
}
function checkRemoteFile($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
// don't download content
curl_setopt($ch, CURLOPT_NOBODY, 1);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
if(curl_exec($ch)!==FALSE)
{
return true;
}
else
{
return false;
}
}
Uwaga: ten bieżący kod pomaga zidentyfikować uszkodzony lub nie znaleziony obraz url to nie pomoże Ci zidentyfikować typu obrazu lub nagłówków
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-23 17:14:20