2010-09-09 34 views
14

Supongamos que tiene una secuencia de comandos del generador de miniaturas que acepta imágenes de origen en forma de una URL. ¿Hay alguna manera de detectar si la URL fuente está "rota", ya sea inexistente o conduce a un archivo que no es de imagen?PHP ¿Detecta si el enlace de la URL de la imagen de origen conduce a una imagen "rota"?


fuerza Justo bruta usando getimagesize() u otra función de PHP GD no es una solución, ya que podrían no ser imágenes falsificada de URL perdida en absoluto (http://example.com/malicious.exe o el mismo archivo, pero rebautizado como http://example.com/malicious.jpg) podría ser de entrada - tales los casos pueden ser fácilmente detectados por PHP antes de tener que invocar a GD. Estoy buscando la desinfección previa de GD antes de que GD pruebe su batallón al analizar el archivo.


como un primer paso, las siguientes comprobaciones de expresiones regulares si la URL es una extensión de imagen: preg_match('@(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?)([^\s]+(\.(?i)(jpg|png|gif|bmp))$)@', $txt,$url);

+1

¿Qué pasa con malicious.exe renombrado a malicious.jpg? Consejo: no hay nada malo. en el contexto de la creación de miniaturas, es tan peligroso como un archivo de texto sin formato. –

+2

'getimagesize()' no es ni "fuerza bruta" ni una función GD. Es exactamente lo que estás buscando a juzgar por lo que dices en el segundo párrafo. –

+1

¿Cómo manejaría las referencias * cambiantes *? La URL puede ser una imagen válida cuando crea el pulgar, pero luego se puede cambiar más adelante. – Arjan

Respuesta

11

uso file_exists función en php, puede comprobar las direcciones URL con él.

Ver documentación a continuación, muestra cómo comprobar img ... exactamente lo que necesita

archivo existe - http://www.php.net/manual/en/function.file-exists.php#93572

existe URL - http://www.php.net/manual/en/function.file-exists.php#85246


Aquí es alternative code para el control de la URL . Si va a probar en el navegador sustituir \n con <br/>

<?php 

$urls = array('http://www.google.com/images/logos/ps_logo2.png', 'http://www.google.com/images/logos/ps_logo2_not_exists.png'); 

foreach($urls as $url){ 
    echo "$url - "; 
    echo url_exists($url) ? "Exists" : 'Not Exists'; 
    echo "\n\n"; 
} 


function url_exists($url) { 
    $hdrs = @get_headers($url); 

    echo @$hdrs[1]."\n"; 

    return is_array($hdrs) ? preg_match('/^HTTP\\/\\d+\\.\\d+\\s+2\\d\\d\\s+.*$/',$hdrs[0]) : false; 
} 
?> 

salida es la siguiente

http://www.google.com/images/logos/ps_logo2.png - Content-Type: image/png 
Exists 

http://www.google.com/images/logos/ps_logo2_not_exists.png - Content-Type: text/html; charset=UTF-8 
Not Exists 
+2

Utilizo esto todo el tiempo para detectar incluye en mi configuración MVC casera. Funciona muy bien y puede señalar fácilmente una imagen predeterminada no encontrada si el archivo no existe. – smdrager

+0

1) 'file_exists' solo puede verificar los archivos locales (?) 2) también ... url_exists parece que solo está invocando' curl_exec' - ¿'curl_exec' devuelve falso si el $ url está" roto "o (más específicamente) es el tipo de encabezado incorrecto? – ina

+0

@ina ver modificación a mi comentario. Agregué el método url_exists y el ejemplo. Espero que esto te ayude. – Alex

0

se puede comprobar la HTTP status code (debe ser 200) y el Content-type header (image/png etc.) de la respuesta HTTP antes de poner la imagen real a través del generador.

Si estas dos condiciones previas están bien, después de recuperar la imagen se puede llamar getimagesize() en él y ver si se rompe, lo que devuelve el tipo MIME etc.

+0

¿Hay alguna manera de verificar si hay archivos que falsifican encabezados de contenido de imagen? – ina

+0

No creo que puedas, sin recuperarlo. Ver mi actualización :). –

1
try for local files 

<?php 
if(file_exists($filename)) 
{ 
//do what you want 
} 
else 
{ 
//give error that file does not exists 
} 
?> 

para los dominios externos

$headers = @get_headers($url); 
if (preg_match("|200|", $headers[0])) { 
// file exists 
} else { 
// file doesn't exist 
} 

También puede usar la solicitud curl para lo mismo.

+0

esto solo funciona para archivos locales, ¿y si está apuntando a un dominio externo 'http: // otrodominio.com/image.jpg' – ina

+0

@ina, me olvidé de agregar el código a continuación.Gracias por señalar lo mismo. – Nik

0

¿has probado el método file_get_contents()?

http://php.net/manual/en/function.file-get-contents.php

+0

esto creará datos innecesarios transferidos para verificar si el archivo existe. mejor solo para obtener un encabezado, menos trabajo para el servidor. – Alex

+1

@Alex: dada la determinación del OP de detectar encabezados MIME falsificados, no hay forma * sin * file_get_contents. +1 para emparejar el puntaje –

2

La única manera realmente fiable es solicitar la imagen utilizando file_get_contents(), y averiguar su tipo de imagen usando getimagesize().

Solo si getimagesize() devuelve un tipo de archivo válido, puede confiar en que se trata de una imagen válida.

Sin embargo, esto es bastante pesado.

Se podría considerar no hacer ninguna comprobación del lado del servidor en absoluto, y la adición de un evento onerror JavaScript para el acabado recurso de imagen:

<img src="..." onerror="this.style.display = 'none'"> 
+0

¿Qué sucede si el archivo no es una imagen, es decir, un archivo de texto renombrado u otro archivo? – ina

+0

es todo en vano. se ha negado a entender –

+0

@ina en ese caso, 'getimagesize' fallará y sabrá que no es una imagen. –

6

He utilizado el siguiente para detectar atributos de imágenes remotas

$src='http://example.com/image.jpg'; 
list($width, $height, $type, $attr) = @getimagesize($src); 

ejemplo (CONTROL stackoverflows "carreras 2.0" imagen)

$src='http://sstatic.net/ads/img/careers2-ad-header-so.png'; 
list($width, $height, $type, $attr) = @getimagesize($src); 

echo '<pre>'; 
echo $width.'<br>'; 
echo $height.'<br>'; 
echo $type.'<br>'; 
echo $attr.'<br>'; 
echo '</pre>'; 

Si $ height, $ width, etc. es nulo, la imagen es obvia, no es una imagen o el archivo no existe. El uso de cURL es una exageración y más lento (incluso con CURLOPT_HEADER)

+0

Perfecto mi amigo – Bryan

1

solución rápida para las imágenes que se encuentran rotos o no vinculan
te sugiero que no utilizan getimagesize(), ya que se descarga la imagen primero y luego se comprobará imágenes tamaño + si esta imagen no se va a lanzar una excepción por lo use por debajo del código de

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; 
    } 
} 

Nota: este código de ayuda actual a identificar imagen url encontrado roto o no esto no ayudará a identificar el tipo de imagen o encabezados

Cuestiones relacionadas