2008-10-13 26 views
13

¿Existe una forma eficiente de detectar si un archivo jpeg está dañado?¿Detecta eficientemente el archivo jpeg dañado?

Antecedentes:
  soluciones tiene que trabajar desde dentro de un script php
  los archivos JPEG son en el disco
  comprobación manual hay ninguna opción (usuario cargan los datos)

sé que imagecreatefromjpeg(string $filename); puede hazlo. Pero es bastante lento al hacerlo.

¿Alguien sabe una solución más rápida/más eficiente?

Respuesta

16

Desde la línea de comandos, puede usar jpeginfo para averiguar si un archivo jpeg es correcto o no.

$ JPEGInfo -c test.jpeg

test.jpeg 260 x 264 de 24 bits JFIF N 15332 [OK]

Debe ser trivial para llamar JPEGInfo de php.

+2

nota de la observación de la OP acerca lenta: se bifurcan un proceso externo y procesar la devolución es posiblemente incluso más lento que imagecreatefromjpeg()! – Willem

+0

Puede que tengas razón, no tengo idea de qué tan lento es imagecreatefromjpeg. Supongo que la única forma de encontrarlo es comparar ambos. – Pat

+0

Aunque realizar un proceso externo es lento, es la mejor opción. PHP es horrible en cuanto a los requisitos de memoria y velocidad cuando lee archivos de imágenes. Véase también [respuesta Travis'] (http://stackoverflow.com/questions/198438/efficiently-detect-corrupted-jpeg-file/2761021#2761021). – Jacco

7

Mi más simple (y más rápido) solución:


function jpeg_file_is_complete($path) { 
    if (!is_resource($file = fopen($path, 'rb'))) { 
     return FALSE; 
    } 
    // check for the existence of the EOI segment header at the end of the file 
    if (0 !== fseek($file, -2, SEEK_END) || "\xFF\xD9" !== fread($file, 2)) { 
     fclose($file); 
     return FALSE; 
    } 
    fclose($file); 
    return TRUE; 
} 

function jpeg_file_is_corrupted($path) { 
    return !jpeg_file_is_complete($path); 
} 

Nota: Esto sólo se detecta una estructura de archivo dañado, y no detecta los datos de imagen dañados.

+1

Esta es, en efecto rápido, pero no detecta datos incompletos (que se muestra como una parte inferior negro de la imagen jpeg). – Jacco

+0

Muy bueno para encontrar imágenes que no se transfirieron por completo. –

+0

Este método es rápido pero no es preciso. El JPEG válido puede tener bytes al final después de FFD9 y el JPEG no válido puede finalizar con FFD9. Entonces este método da falsos positivos y negativos positivos. – Tom

-1

También puede intentar generar hash de archivo basado en MD5 y usarlo como suma de comprobación para validar datos JPEG en varios pasos. Por ejemplo, después de leer desde el archivo, luego de la transferencia, etc.

+0

Esto funcionaría para mover el archivo de alrededor internamente, no para la detección de archivos que están dañados antes de entrar en el sistema. – Jacco

6

FYI - He usado the method above (jpeg_file_is_complete) para probar archivos JPEG que sé que están corruptos (cuando los cargo en un navegador, por ejemplo, la parte inferior es gris - es decir, la imagen está "cortada"). De todos modos, cuando ejecuté la prueba anterior en esa imagen, NO la detecté como corrupta.

Hasta ahora, el uso de imagecreatefromjpeg() funciona, pero no es muy rápido. Descubrí que usar jpeginfo también funciona para detectar este tipo de imágenes corruptas, y es MÁS RÁPIDO que imagecreatefromjpeg (ejecuté un punto de referencia en mi PHP usando microtime()).

+1

gracias, la comprobación de la funcionalidad jpeg_file_is_complete() todavía estaba en mi lista de cosas que hacer. me ahorra el tiempo :) – Jacco

+2

Un seguimiento rápido. He estado usando con éxito "jpeginfo" para probar JPG y ha funcionado muy bien. Es rápido y no da falsos positivos. – Travis

-3

Tengo una otra solución con una simple getimagesize()

if(!getimagesize($image_url)) echo 'Image is corrupt or not readable'; 
+0

los datos exif corruptos pueden corromper el resto del archivo, pero este método no los detectará. – Sam

+0

Desde el documento PHP: [* "** Precaución ** Esta función espera que el nombre de archivo sea un archivo de imagen válido. Si se proporciona un archivo que no es de imagen, puede detectarse incorrectamente como una imagen y la función volverá a funcionar correctamente. pero la matriz puede contener valores sin sentido. No use getimagesize() para verificar que un archivo dado sea una imagen válida. Use en su lugar una solución especialmente diseñada como la extensión Fileinfo. "*] (http://php.net /manual/en/function.getimagesize.php) – Pang

0

Inténtelo que

<?php 
$img = $_GET['img']; 
$str_exec = 'jpeginfo -c /chroot/home/www/html/media/'.$img; 
$result = exec($str_exec); 
if(strpos($result, 'ERROR')) 
{ 
    echo 'ERROR'; 
} 
else 
{ 
    echo 'OK'; 
} 
?> 
+0

Cuidado con el uso de esto en un servidor web público: está pasando la entrada de GET directamente a la línea de comando, lo que permite un shell shell exploit: ¿Qué sucede si llamo a la página anterior con ' ? img = rm - rf .'? Probablemente borrará todos los archivos en el directorio actual – PanMan

0

Sólo una pequeña nota- cómo conseguir JPEGInfo para Windows (64 bits)? que no hay binarios Win32/Win64 en GitHub de autor, pero se puede hacer esto:

1) agarrar jpeginfo.exe de este archivo: https://github.com/MoserMichael/cstuff/raw/master/img-archive/img-archive.zip

2) agarrar cygwin1.dll de este archivo: ftp://mirror.internode.on.net/pub/cygwin/x86/release/cygwin64/cygwin64-2.6.0-1.tar.xz

Pruébelo desde la línea de comandos si funciona: jpeginfo --help. Si hay información, funciona bien.

Cómo probar JPEGInfo de salida?

jpeginfo devuelve 0 si el archivo está bien, pero devuelve 1, no solo cuando no lo es, sino también cuando encuentra algo que no comprende. A continuación, se genera un mensaje como este:

Warning: unknown JFIF revision number 2.01 1280 x 720 24bit JFIF N 122550 [WARNING]

En los archivos dañados que devuelve 1 y mensaje como este:

1328 x 2048 24bit JFIF N 1310080 Premature end of JPEG file [WARNING]

Por lo tanto es posible que desee probar la salida real no sólo código de retorno .

Cuestiones relacionadas