2009-08-08 13 views
5

Tengo el siguiente código:Compruebe el tipo de archivo de imagen y tamaño antes de la carga de archivos en php

$filecheck = basename($_FILES['imagefile']['name']); 
    $ext = substr($filecheck, strrpos($filecheck, '.') + 1); 
    if (($ext == "jpg" || $ext == "gif" || $ext == "png") && ($_FILES["imagefile"]["type"] == "image/jpeg" || $_FILES["imagefile"]["type"] == "image/gif" || $_FILES["imagefile"]["type"] == "image/png") && 
    ($_FILES["imagefile"]["size"] < 2120000)){ 
} else { 
echo "F2"; 
die(); 
} 

lo que tengo que hacer es comprobar si el archivo subido es un archivo JPG/GIF/PNG y que está a menos de 2 megas de tamaño.

Si es más grande que 2 megas, o no el tipo de archivo correcto, necesito devolver/repetir F2 (código de error para api).

Cuando uso el código anterior para procesar un archivo de 70k jpg, devuelve F2.

SUBNOTA la im im cargando tiene una extensión de .JPG. ¿Podría el caso ser un factor? Si es así, ¿cómo me acomodo para eso?

+1

Para responder a su subnota: '$ ext = strtolower (substr ($ filecheck, strrpos ($ filecheck, '.') + 1));' – jimyi

Respuesta

22

Tenga en cuenta que es posible que no desee confiar en las extensiones para determinar el tipo de archivo. Sería bastante fácil para alguien para cargar un archivo ejecutable con una extensión .png, por ejemplo. Un tipo de mimo también puede ser falsificado fácilmente por un cliente malicioso para pasarlo como una imagen. Confiar en esa información es un riesgo de seguridad.

PHP Documentation:
El tipo mime del archivo, si el navegador proporciona esta información. Un ejemplo sería "image/gif". Sin embargo, este tipo de mimo no se verifica en el lado de PHP y, por lo tanto, no da por hecho su valor.

intente cargar las imágenes con gd (getimagesize()) para asegurarse de que en realidad son imágenes válidas (y no sólo archivos al azar pretendidos con el encabezado de un archivo de imagen ... finfo_file se basa en los encabezados).

if($_FILES["imagefile"]["size"] >= 2120000) { 
    echo "F2"; 
    die(); 
} else { 
    $imageData = @getimagesize($_FILES["imagefile"]["tmp_name"]); 

    if($imageData === FALSE || !($imageData[2] == IMAGETYPE_GIF || $imageData[2] == IMAGETYPE_JPEG || $imageData[2] == IMAGETYPE_PNG)) { 
     echo "F2"; 
     die(); 
    } 
} 

Si realmente tiene que utilizar la extensión para verificar si el archivo es una imagen, utilice strtolower() poner la extensión en minúsculas.

$filecheck = basename($_FILES['imagefile']['name']); 
$ext = strtolower(substr($filecheck, strrpos($filecheck, '.') + 1)); 

if (!(($ext == "jpg" || $ext == "gif" || $ext == "png") && ($_FILES["imagefile"]["type"] == "image/jpeg" || $_FILES["imagefile"]["type"] == "image/gif" || $_FILES["imagefile"]["type"] == "image/png") && 
    ($_FILES["imagefile"]["size"] < 2120000))){ 
    echo "F2"; 
    die(); 
} 
+0

Extra, metafísico +1 para una respuesta excelente. –

5

SUBNOTA la im im carga tiene una extensión de .JPG. ¿Podría el caso ser un factor? Si es así, ¿cómo me acomodo para eso?

Sí, ese es el problema. Usted debe agregar strtolower() para esta línea:

$ext = substr($filecheck, strrpos($filecheck, '.') + 1); 

como:

$ ext = strtolower (substr ($ Todo incluído, strrpos ($ Todo incluído,) + 1) '');

Eso solucionará su problema actual. Pero técnicamente, no debería preocuparse por las extensiones de archivos, en realidad solo debería verificar el tipo MIME

+0

tipo MIME de hecho. El archivo también podría llamarse .jpeg. –

+0

Confiar en esa información ** es un riesgo de seguridad **. Por favor, lea mi respuesta a continuación. –

5

Las comparaciones como $ext == "jpg" solo comprueban que el $ext es exactamente "jpg".

Es posible que desee utilizar strtolower en $ ext antes de hacer esas comparaciones, para hacer frente a la situación ".JPG".


Si está usando PHP < = 5.2, es posible que desee utilizar mime_content_type para comprobar el tipo de contenido de los archivos, en lugar de depender de $_FILES['imagefile']['name'] y/o $_FILES["imagefile"]["type"], que son a la vez enviado por el cliente - y puede, como tal, ser falsificado.

Si está usando PHP> = 5.3, es posible que desee considerar la nueva extensión fileinfo, y es finfo_file función


Para el tamaño del archivo, ya está utilizando $_FILES["imagefile"]["size"]; eso está bien, supongo, pero sólo lo sabré cuando el archivo se ha cargado - aún así, no hay forma real de comprobar ese tipo de cosas antes de cargar, me temo ...


se Es posible que pueda encontrar algún código JS para hacer una primera verificación previa de la extensión antes de que se cargue el archivo, pero igual tendrá que verificar en el lado del servidor, ya que cualquier cosa hecha desde el lado del cliente no es inherentemente segura.

No estoy seguro de que pueda hacer lo mismo con el tamaño del archivo, aunque ...

Algunos navegadores pueden admitir un campo oculto llamado MAX_FILE_SIZE (consulte la documentación acerca de file upload); pero no estoy seguro que es realmente compatible (nunca visto que se usa, en realidad, así que probablemente no es :-()


Como anotación al margen, es probable que desee para configurar upload_max_filesize, lo que permite subir al menos tan grande como lo que desea (de manera predeterminada, generalmente está configurado en 2MB, entonces ya debería estar bien para usted)

2

PHP es un lenguaje de script del lado del servidor y si las imágenes están en el lado del cliente, no se puede comprobar su tamaño a través de php antes carga.

+0

muy buen punto: se puede usar javascript para verificar el tamaño del archivo y rechazarlo, mientras que * filetype * se puede verificar internamente en el script a través de la respuesta de @Andrew Moore – warren

2

se necesitan dos cosas:

hacer su caso cheque extensión insensible:

if($strtolower($ext == "jpg")){ 
    // do your stuff 
} 

Comprobar si el archivo contiene en realidad una imagen. Una manera fácil de hacer esto es fileinfo:

$finfo = finfo_open(FILEINFO_MIME_TYPE); 
echo finfo_file($finfo, $filename); 
$finfo_close($finfo); 

Una forma alternativa de comprobar si un archivo es realmente una imagen se carga en una biblioteca de imágenes como gd. Si su archivo se puede cargar con éxito, se trata de una imagen.

Tenga en cuenta que las imágenes jpeg pueden tener la extensión .jpg o .jpeg.

3

tomar en cuenta que para Internet Explorer, se someten tipo mime del archivo JPEG como imagen/pjpeg - que es diferente de otros navegadores.

Aquí es una función simple para obtener su tipo MIME en contra de la extensión de archivo:

function mime2ext($mime){ // mime is like image/jpeg 
    $m = explode('/',$mime); 
    $mime = $m[count($m)-1]; // get the second part of the mime type 
    switch($mime){ 
     case 'jpg': 
     case 'jpeg': 
     case 'pjpeg': 
      return 'jpg'; 
      break; 
     case 'png': 
      return 'png'; 
      break; 
     case 'gif': 
      return 'gif'; 
      break; 
    } 
    return ''; 
} 
3

tamaño del archivo es bastante obvio, pero lo que la gente está haciendo arriba para comprobar que es el formato correcto es algo ineficaz, y " inseguro".

Aquí es lo que hago:

if($_FILES["userPicture"]["error"] == 0) { 
// File was uploaded ok, so it's ok to proceed with the filetype check. 
    $uploaded_type = exif_imagetype($_FILES["userPicture"]["tmp_name"]); 
    // What we have now is a number representing our file type. 

    switch($uploaded_type) { 
     case "1": 
      $uploaded_type = "gif"; 
     break; 
     case "2": 
      $uploaded_type = "jpg"; 
     break; 
     case "3": 
      $uploaded_type = "png"; 
     break; 
    } 
} 

Más información en;
http://www.php.net/manual/en/function.exif-imagetype.php

Editar: Esto tiene la ventaja de trabajar "en todos los navegadores", ya que no se basa en el nombre del archivo, o el usuario suministra nada, excepto el valor archivos matriz "error", que nos dice que no había realmente un error

Cuestiones relacionadas