2013-03-24 12 views
7

Sono un principiante di PHP e attualmente sto imparando la parte "Convalida il caricamento del file".PHP Convalida il caricamento file

Ho fatto una pagina test.php contenente codice seguente:

var_dump(@$_FILES['file']['type']); 

In primo luogo, ho caricato un "img.gif" immagine e restituito:

string 'image/gif' (length=9) 

Poi, ho cambiato dell'immagine estensione ".jpg" ed è tornato:

string 'image/jpeg' (length=10) 

Così ho capito $ _FILES [ "file"] [ "tipo"] restituisce solo il file caricato estensione, ma in realtà non ha verificato quale file è.

In questa pagina, http://www.w3schools.com/php/php_file_upload.asp, c'è un codice:

$allowedExts = array("gif", "jpeg", "jpg", "png"); 
$extension = end(explode(".", $_FILES["file"]["name"])); 
if ((($_FILES["file"]["type"] == "image/gif") 
|| ($_FILES["file"]["type"] == "image/jpeg") 
|| ($_FILES["file"]["type"] == "image/jpg") 
|| ($_FILES["file"]["type"] == "image/png")) 
&& ($_FILES["file"]["size"] < 20000) 
&& in_array($extension, $allowedExts)) 

mi chiedo perché i codici di cui sopra controllare estensione del file due volte? Ho cancellato alcuni dei codici precedenti e questo è il mio nuovo codice:

$allowedExts = array("gif", "jpeg", "jpg", "png"); 
$extension = end(explode(".", $_FILES["file"]["name"])); 
if (($_FILES["file"]["size"] < 20000) && in_array($extension, $allowedExts)) 

Il mio codice è corretto? O hai qualche modo migliore per convalidare il file di upload è un'immagine?

Grazie!

+1

Perché il mio post ha avuto un downvote? Voglio solo assicurarmi che $ _FILES ["file"] ["tipo"] non sia necessario nei codici di w3schools – nut

risposta

12

È necessario passare il nome_tmp del file * a getimagesize, esso fornirà la dimensione e il tipo dell'immagine (se si tratta di un'immagine). Se l'argomento passato è un file ma non un'immagine restituisce false, ciò consentirà di convalidare.

Modifica: l'unico metodo affidabile per la convalida dell'immagine consiste nel crearne una copia utilizzando GD o Imagick - getimagesize can be easily hacked.

*: Voglio dire, il file temporale creato dopo il caricamento.

Ad esempio:

if ($_SERVER['REQUEST_METHOD'] === 'POST') 
{ 
    $file = $_FILES['file']['tmp_name']; 
    if (file_exists($file)) 
    { 
     $imagesizedata = getimagesize($file); 
     if ($imagesizedata === FALSE) 
     { 
      //not image 
     } 
     else 
     { 
      //image 
      //use $imagesizedata to get extra info 
     } 
    } 
    else 
    { 
     //not file 
    } 
} 

Questo codice utilizza file_exists solo per essere generale. Nel caso in cui nessun file è stato caricato si otterrebbe $_FILES['file']['size'] = 0, $_FILES['file']['tmp_name'] = '' e $_FILES['file']['error'] = 4. Vedi anche is_readable. Per i valori di errore vedere file upload errors explained a php.net.

+0

grazie per aver menzionato la funzione getimagesize – nut

+2

Si noti che controlla se si tratta di un'immagine, ma ciò non significa che non si tratti di un'immagine che è stata mitigata, si veda: http://php.webtutor.pl/en/ 2011/05/13/php-code-injection-a-simple-virus-written-in-php-and-carried-in-a-jpeg-image/Raccomando di ricreare l'immagine usando funzioni come imagecreatefromstring e convertendola in per esempio png. - Arie 50 minuti fa – Arie

1
$allowedExts = array("gif", "jpeg", "jpg", "png"); 
$extension = end(explode(".", $_FILES["file"]["name"])); 
if ((($_FILES["file"]["type"] == "image/gif") 
|| ($_FILES["file"]["type"] == "image/jpeg") 
|| ($_FILES["file"]["type"] == "image/jpg") 
|| ($_FILES["file"]["type"] == "image/png")) 
&& ($_FILES["file"]["size"] < 20000) 
&& in_array($extension, $allowedExts)) 

La verifica avviene due volte perché, l'estensione del file e 'il tipo di file' possono essere diverse, in modo che qualcuno non può caricare file eseguibile con estensione .png.

Nel codice modificato, è possibile caricare un diverso tipo di file con estensione modificata. come se potessero caricare un documento word con estensione ".png".

Il tuo nuovo codice controlla semplicemente l'estensione e non ha il doppio controllo.

+3

Ho caricato un file exe con estensione png, la pagina restituita: stringa 'image/png' (lunghezza = 9) – nut

0

Il nuovo codice controlla solo l'estensione del file e la dimensione del file. Non controlla il tipo del file.

Raccomanderò caldamente di usare il vecchio codice perché lì controlla anche il tipo di file.

+1

var_dump (@ $ _ FILES ['file'] ['type']) ha restituito la stringa 'image/png' (length = 9) per un file exe ma con un'estensione png, quindi non ha controllato il tipo di file ma solo il estensione. – nut