21 votes

Quelle est la meilleure façon de créer un formulaire de téléchargement de fichier unique en PHP ?

J'ai trouvé quelques exemples en ligne, mais j'aimerais que les personnes qui utilisent PHP quotidiennement me fassent part de leurs commentaires sur les problèmes potentiels de sécurité ou de performances, ainsi que de leurs solutions.

Notez que je ne suis intéressé que par le téléchargement d'un seul fichier à la fois.

Idéalement, aucun plugin de navigateur ne serait nécessaire (Flash/Java), bien qu'il serait intéressant de connaître les avantages de l'utilisation d'un plugin.

J'aimerais connaître le meilleur code de formulaire HTML et le meilleur code de traitement PHP.

34voto

Drew Noakes Points 69288

Tutoriel sur le téléchargement de fichiers

HTML

<form enctype="multipart/form-data" action="action.php" method="POST">
  <input type="hidden" name="MAX_FILE_SIZE" value="1000000" />
  <input name="userfile" type="file" />
  <input type="submit" value="Go" />
</form>
  • action.php est le nom d'un fichier PHP qui traitera le téléchargement (voir ci-dessous).
  • MAX_FILE_SIZE doit apparaître immédiatement avant l'entrée de type file . Cette valeur peut facilement être manipulée par le client et il ne faut donc pas s'y fier. Son principal avantage est d'avertir l'utilisateur que son fichier est trop volumineux, avant qu'il ne l'ait téléchargé.
  • Vous pouvez changer le nom de l'entrée avec le type file mais assurez-vous qu'il ne contient pas d'espace. Vous devez également mettre à jour la valeur correspondante dans le fichier PHP (ci-dessous).

PHP

<?php
$uploaddir = "/www/uploads/";
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);

echo '<pre>';
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
    echo "Success.\n";
} else {
    echo "Failure.\n";
}

echo 'Here is some more debugging info:';
print_r($_FILES);
print "</pre>";
?>

Le dossier upload-to ne doit pas être situé à un endroit accessible via HTTP, sinon il serait possible de télécharger un script PHP et de l'exécuter sur le serveur.

Impression de la valeur de $_FILES peut donner un indice sur ce qui se passe. Par exemple :

    Array
    (
        \[userfile\] => Array
        (
            \[name\] => Filename.ext
            \[type\] => 
            \[tmp\_name\] => 
            \[error\] => 2
            \[size\] => 0
        )
    )

Cette structure donne des informations sur le nom du fichier, le type MIME, la taille et le code d'erreur.

Codes d'erreur

0 Indique qu'il n'y a pas eu d'erreur et que le fichier a été téléchargé avec succès.
1 Indique que le fichier dépasse la taille maximale définie dans le php.ini. Si vous souhaitez modifier la taille maximale des fichiers, vous devez ouvrir votre fichier php.ini, identifier la ligne suivante : upload_max_filesize = 2M et modifier la valeur de 2M (2MB) en fonction de vos besoins.
2 Indique que la taille maximale du fichier définie manuellement, dans un script de la page, a été dépassée.
3 Indique que le fichier n'a été téléchargé que partiellement.
4 Indique que le fichier n'a pas été spécifié (champ vide).
5 Pas encore défini
6 Indique qu'il n'y a pas de dossier temporaire.
7 Indique que le fichier ne peut pas être écrit sur le disque.

php.ini Configuration

Lorsque vous exécutez cette configuration avec des fichiers plus importants, vous pouvez recevoir des erreurs. Vérifiez votre php.ini pour ces clés :

max_execution_time = 30
upload_max_filesize = 2M

Augmenter ces valeurs comme il convient peut aider. Si vous utilisez Apache, les modifications apportées à ce fichier nécessitent un redémarrage.

La valeur maximale de la mémoire autorisée (définie via memory_limit ) ne joue pas de rôle ici car le fichier est écrit dans le répertoire tmp au fur et à mesure qu'il est téléchargé. L'emplacement du répertoire tmp est contrôlé de manière optionnelle via la fonction upload_tmp_dir .

Vérification des mimetypes de fichiers

Vous devez vérifier le type de fichier que l'utilisateur télécharge - la meilleure pratique consiste à le valider par rapport à une liste de types de fichiers autorisés. Un risque potentiel d'autoriser n'importe quel fichier est que un utilisateur peut potentiellement télécharger du code PHP sur le serveur et l'exécuter. .

Vous pouvez utiliser le très utile fileinfo (qui remplace l'ancienne extension mime_content_type ) pour valider les types de mime.

// FILEINFO_MIME set to return MIME types, will return string of info otherwise
$fileinfo = new finfo(FILEINFO_MIME);
$file = $fileinfo->file($_FILE['filename']);

$allowed_types = array('image/jpeg', 'image/png');
if(!in_array($file, $allowed_types))
{
    die('Files of type' . $file . ' are not allowed to be uploaded.');
}
// Continue

Plus d'informations

Pour en savoir plus sur la gestion des téléchargements de fichiers, consultez le site Web de la Commission européenne. Manuel PHP.net .

Pour PHP 5.3 et plus

//For those who are using PHP 5.3, the code varies.
$fileinfo = new finfo(FILEINFO_MIME_TYPE);
$file = $fileinfo->file($_FILE['filename']['tmp_name']);
$allowed_types = array('image/jpeg', 'image/png');
if(!in_array($file, $allowed_types))
{
    die('Files of type' . $file . ' are not allowed to be uploaded.');
}
// Continue

Plus d'informations

Pour plus d'informations sur FILEINFO_MIME_TYPE, consultez le site de la Commission européenne. Documentation de PHP.net .

5voto

Ross Points 19037

Lisez le cette introduction qui devrait vous dire tout ce que vous devez savoir. Les commentaires des utilisateurs sont également très utiles.

4voto

eyelidlessness Points 28034

Le principal avantage de Flash est qu'il vous permet de télécharger plusieurs fichiers. Le principal avantage de Java est qu'il permet le glisser-déposer à partir du système de fichiers. Désolé de ne pas avoir répondu à la question centrale, mais j'ai pensé que je devais le faire car c'est assez simple.

3voto

cole Points 341

La sécurité est une chose assez importante en ce qui concerne les téléchargements de fichiers, l'ajout d'un .htaccess au dossier uploads qui empêche l'exécution de scripts à partir de celui-ci pourrait être pratique pour ajouter juste une couche supplémentaire de sécurité.

.htaccess

Options -Indexes
Options -ExecCGI
AddHandler cgi-script .php .php3 .php4 .phtml .pl .py .jsp .asp .htm .shtml .sh .cgi 

Référence : http://www.mysql-apache-php.com/fileupload-security.htm

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X