web-dev-qa-db-fra.com

Comment vérifier les types de fichiers des fichiers téléchargés en PHP?

Sur le site PHP, la seule vraie vérification qu’ils suggèrent est d’utiliser is_uploaded_file() ou move_uploaded_file(), ici . Bien sûr, vous ne veulent généralement pas que l'utilisateur télécharge un type de fichier, pour diverses raisons.

Pour cette raison, j'ai souvent utilisé une vérification de type MIME "stricte". Bien sûr, cela est très imparfait car souvent les types MIME sont incorrects et les utilisateurs ne peuvent pas télécharger leur fichier. Il est également très facile de truquer et/ou de changer. Et avec tout cela, chaque navigateur et système d'exploitation les traite différemment.

Une autre méthode consiste à vérifier l'extension, qui est bien sûr encore plus facile à changer que le type MIME.

Si vous ne voulez que des images, utiliser quelque chose comme getimagesize() fonctionnera.

Qu'en est-il des autres types de fichiers? PDF, documents Word ou fichiers Excel? Ou même des fichiers texte uniquement?

Modifier: Si vous n'avez pas mime_content_type ou Fileinfo et system ("file -bi $ uploadfile ") vous donne le mauvais type de fichier, quelles sont les autres options?

47
Darryl Hein

Jetez un œil à mime_content_type ou Fileinfo . Ce sont des commandes intégrées PHP pour déterminer le type d'un fichier en regardant le contenu du fichier. Vérifiez également les commentaires sur les deux pages ci-dessus, il y a d'autres bonnes suggestions.

Personnellement, j'ai eu de la chance en utilisant quelque chose qui est essentiellement system("file -bi $uploadedfile"), mais je ne sais pas si c'est la meilleure méthode.

33
davr

À mon humble avis, toutes les méthodes de vérification de type MIME sont inutiles.

Supposons que vous en ayez un qui devrait avoir le type MIME application/pdf. Les méthodes standard essaient de trouver quelque chose qui ressemble à un en-tête PDF (%PDF- ou smth. comme ça) et ils retourneront "D'accord, il semble que ce soit un PDF" en cas de succès. Mais en fait, cela ne veut rien dire. Vous pouvez télécharger un fichier contenant uniquement %PDF-1.4 et il passera la vérification MIME.

Je veux dire si le fichier a un type MIME attendu - il passera toujours la vérification de type MIME sinon le résultat n'est pas défini.

14
Sudden Def

J'ai utilisé mime_content_type qui est compatible avec PHP 5.2, car je ne peux utiliser ni Fileinfo (il nécessite PHP 5.3) ni la fonction system(), qui est désactivé par mon fournisseur. Par exemple, je vérifie si un fichier est un fichier texte:

if (strcmp(substr(mime_content_type($f),0,4),"text")==0) { ... }

Vous pouvez voir un exemple complet dans mon "écouteur de répertoire et de sous-répertoire PHP et visionneuse de fichiers et téléchargeur" ​​sur: http://www.galgani.it/software_repository/index.php

2
Francesco Galgani
if(isset($_FILES['uploaded'])) {
    $temp = explode(".", $_FILES["uploaded"]["name"]);

    $allowedExts = array("txt","htm","html","php","css","js","json","xml","swf","flv","pdf","psd","ai","eps","eps","ps","doc","rtf","ppt","odt","ods");

    $extension = end($temp);
    if( in_array($extension, $allowedExts)) {
       //code....

    } else {
        echo "Error,not Documentum type...";
    }
}

Je suppose que vous allez avoir une liste blanche fixe de types de fichiers que vous accepterez.

Pour chacun de ces types, vous devrez utiliser différentes techniques pour vérifier qu'il s'agit d'exemples valides de ce format.

Il y a deux questions liées:

  • Cela ressemble-t-il à peu près au type approprié? (Pour JPEG, vous pouvez vérifier les en-têtes, comme vous l'avez mentionné. Pour de nombreux formats basés sur Unix, vous pouvez vérifier le "cookie magique".)

  • Est-ce en fait un exemple valide de ce type (par exemple, pour tout format de type XML, vous pouvez valider par rapport à une DTD.)

Je pense que, pour chaque format, vous devriez poser des questions distinctes pour chacun, car la réponse sera assez différente pour les PDF par rapport aux fichiers Zip.

2
Oddthinking

Voici la fonction file_mime_type d'iZend:

function file_mime_type($file, $encoding=true) {
    $mime=false;

    if (function_exists('finfo_file')) {
        $finfo = finfo_open(FILEINFO_MIME);
        $mime = finfo_file($finfo, $file);
        finfo_close($finfo);
    }
    else if (substr(PHP_OS, 0, 3) == 'WIN') {
        $mime = mime_content_type($file);
    }
    else {
        $file = escapeshellarg($file);
        $cmd = "file -iL $file";

        exec($cmd, $output, $r);

        if ($r == 0) {
            $mime = substr($output[0], strpos($output[0], ': ')+2);
        }
    }

    if (!$mime) {
        return false;
    }

    if ($encoding) {
        return $mime;
    }

    return substr($mime, 0, strpos($mime, '; '));
}
1
iZend

Pour PHP> = 5.3.0, vous pouvez utiliser la fonction finfo_file ( finfo_file ) de php pour obtenir les informations sur le fichier.

Pour PHP <5.3.0, vous pouvez utiliser la commande file de votre système pour obtenir les informations sur le fichier.

Alors, faites-le dans une seule fonction,

var_dump(mime_type("wiki templete.txt"));   // print string(10) "text/plain"

function mime_type($file_path)
{
    if (function_exists('finfo_open')) {
        $finfo = new finfo(FILEINFO_MIME_TYPE, null);
        $mime_type = $finfo->file($file_path);
    }
    if (!$mime_type && function_exists('passthru') && function_exists('escapeshellarg')) {
        ob_start();
        passthru(sprintf('file -b --mime %s 2>/dev/null', escapeshellarg($file_path)), $return);
        if ($return > 0) {
            ob_end_clean();
            $mime_type = null;
        }
        $type = trim(ob_get_clean());
        if (!preg_match('#^([a-z0-9\-]+/[a-z0-9\-\.]+)#i', $type, $match)) {
            $mime_type = null;
        }
        $mime_type = $match[1];
    }
    return $mime_type;
}

MimeTypes

0
Kris Roofe