Comment uploader un fichier vers son site via http ?

Comme ça revient très souvent sur les forums voici un tutorial extrait de la documentation de php. Celui-ci est basé sur l'exemple d'upload d'image gif d'un poids inférieur à 20ko et une taille inférieure ou égale à 100 x 100 pixel maximum !
Le fichier final sera copié dans le répertoire images_up qui se trouve à la racine du fichier de traitement du formulaire d'upload.


Upload simple



Le formulaire :
<html>
<head>
<title>Upload de fichier</title>
</head>
<body>
<form name="formu" action="traitement.php" method="post" enctype="multipart/form-data">
On remarque qu'il faut ajouter entype="multipart/form-data" pour uploader un fichier
Votre fichier <input type="file" name="fichier" accept="image/gif" /><br/>
<input type="submit" value="Go !!!!" />
</form>
</body>
</html>
Maintenant le traitement du formulaire.
Dans ce tutorial les codes sont écrits pour la configuration suivante :

Dans traitement.php nous récupérons les informations de notre fichier dans un tableau super global $_FILES ! celui ci contient :

Voici un exemple de traitement du formulaire précédent : <?php
if (isset($_FILES['fichier']))
{
//$_FILES existe on récupère les infos qui nous intéressent
$fichier=$_FILES['fichier']['name'];//nom réel de l'image
$size=$_FILES['fichier']['size']; //poids de l'image en octets
$tmp=$_FILES['fichier']['tmp_name'];//nom temporaire de l'image (sur le serveur)
$type=$_FILES['fichier']['type'];//type de l'image
//On récupère la taille de l'image
list($width,$height)=getimagesize($tmp);
if (
is_uploaded_file($tmp)) //permet de vérifier si le fichier a été uplodé via http
{
//vérification du type de l'img, son poids et sa taille
if ($type=="image/gif" && $size<=20500 && $width<=100 && $height<=100 )
{
// type mime gif, poids < à 20500 octets soit environ 20Ko, largeur = hauteur = 100px
//Pour supprimer les espaces dans les noms de fichiers car celà entraîne une erreur lorsque vous voulez l'afficher
$fichier = preg_replace ("` `i","",$fichier);//ligne facultative :)
//On vérifie s'il existe une image qui a le même nom dans le répertoire
if (file_exists('./images_up/'.$fichier))
{
//Le fichier existe on rajoute dans son nom le timestamp du moment pour le différencier de la première (comme cela on est sûr de ne pas avoir 2 images avec le même nom :) )
$nom_final= preg_replace("`.gif`is",date("U").".gif",$fichier);
}
else {
$nom_final=$fichier; //l'image n'existe pas on garde le même nom
}
//on déplace l'image dans le répertoire final
move_uploaded_file($tmp,'./images_up/'.$nom_final);
//Message indiquant que tout s'est bien passé
echo "L'image a été uploadée avec succès<br/>";
}
else {
//Le type mime, ou la taille ou le poids est incorrect
echo 'Votre image a été rejetée (poids, taille ou type incorrect)';
}
}
}
//Pour tester si l'image est bien à sa place
echo '<img src="./images_up/'.$nom_final.'" border="0" />';
echo
'<br/>';
echo
'<a href="javascript:history.back();">Retour</a>';
?>

Upload multiple:

Pour l'upload multiple il `suffit` d'utiliser la notation tableau (fichier[]) dans le nom des balises input de type file
Le formulaire devient donc :

<html>
<head>
<title>Upload de fichier</title>
</head>
<body>
<form name="formu" action="traitement.php" method="post" enctype="multipart/form-data">
On remarque qu'il faut ajouter entype="multipart/form-data" pour uploader un fichier
fichier 1 <input type="file" name="fichier[]" accept="image/gif" /><br />
fichier 2 <input type="file" name="fichier[]" accept="image/gif" /><br />
fichier 3 <input type="file" name="fichier[]" accept="image/gif" /><br />
fichier 4 <input type="file" name="fichier[]" accept="image/gif" /><br />
fichier 5 <input type="submit" value="Go !!!!" />
</form>
</body>
</html>

Pour le traitement, on utilisera une boucle foreach dans laquelle on vérifiera les informations relatives à nos fichiers et on validera ou non ces fichiers !

<?php
if (isset($_FILES['fichier']))
{
//$_FILES existe
foreach ($_FILES['fichier']['name'] as $key => $value) {
$fichier=$value;//nom reel de l'image
$size=$_FILES['fichier']['size'][$key]; //poids de l'image en octets
$tmp=$_FILES['fichier']['tmp_name'][$key];//nom temporaire de l'image (sur le serveur)
$type=$_FILES['fichier']['type'][$key];//type de l'image
//On récupère la taille de l'image
list($width,$height)=getimagesize($tmp);
if (
is_uploaded_file($tmp)) //permet de vérifier si le fichier a été uplodé via http
{
//vérification du type de l'img, son poids et sa taille
if ($type=="image/gif" && $size<=20500 && $width<=100 && $height<=100 )
{
// type mime gif, poids < à 20500 octets soit environ 20Ko, largeur = hauteur = 100px
//Pour supprimer les espaces dans les noms de fichiers car celà entraîne une erreur lorsque vous voulez l'afficher
$fichier = preg_replace ("` `i","",$fichier);//ligne facultative :)
//On vérifie s'il existe une image qui a le même nom dans le répertoire
if (file_exists('./images_up/'.$fichier))
{
//Le fichier existe on rajoute dans son nom le timestamp du moment pour le différencier de la première (comme cela on est sûr de ne pas avoir 2 images avec le même nom :) )
$nom_final= preg_replace("`.gif`is",date("U").".gif",$fichier);
}
else {
$nom_final=$fichier; //l'image n'existe pas on garde le même nom
}
//on déplace l'image dans le répertoire final
if (move_uploaded_file($tmp,'./images_up/'.$nom_final)) {
//Message indiquant que tout s'est bien passé
//Pour le test on affiche l'image
echo '<img src="./images_up/'.$nom_final.'" border="0" />';
echo
'<br/>';
}
else {
//l'image ne peut être déplacée, on supprime le fichier temporaire
@ unlink ($tmp);
echo
'L\'image n\'a pu être déplacée !';
}

}
else {
//Le type mime, ou la taille ou le poids est incorrect
echo 'Votre image a été rejetée (poids, taille ou type incorrect)';
}
}
}
}
echo
'<a href="javascript:history.back();">Retour</a>';
?>

Gestion des erreurs d'upload

Les erreurs qui se produisent pendant l'upload sont renseignées par le champ error du tableau $_FILES
Les différentes erreurs :

Pour effectuer la gestion des erreurs, une petite fonction (afin d'alléger un peu le code)
<?php
function up_error($code,$nom) {
switch (
$code) {
case
'0' : $erreur = 'Pas d\'erreur';$valid = true;break;
case
'1' : $erreur = 'Votre fichier `'.$nom.'` dépasse la taille maximale d\'upload autorisée par PHP( '.get_cfg_var('upload_max_filesize').' )';$valid = false;break;
case
'2' : $erreur = 'Votre fichier dépasse la taille maximale demandée par le Webmestre';$valid = false;break;
case
'3' : $erreur = 'Le fichier n\'a pas été totalement uploadé !!!';$valid = false;break;
case
'4' : $erreur = 'Aucun fichier téléchargé !!!';$valid = false;break;
default :
$erreur = 'L\'upload a rencontré une erreur inconnue !!!';$valid = false; break;
}
$return[] = $valid;
$return[] = $erreur;
return
$return;
}
?>

Le 1er script avec la gestion d'erreurs :
<?php
if (isset($_FILES['fichier']))
{
//$_FILES existe on récupère les infos qui nous intéressent
$fichier=$_FILES['fichier']['name'];//nom réel de l'image
$size=$_FILES['fichier']['size']; //poid de l'image en octets
$tmp=$_FILES['fichier']['tmp_name'];//nom temporaire de l'image (sur le serveur)
$type=$_FILES['fichier']['type'];//type de l'image
$error = $_FILES['fichier']['error'];
$retour = up_error($error,$fichier);
if (
$retour[0] === true) {
//On récupère la taille de l'image
list($width,$height)=getimagesize($tmp);
if (
is_uploaded_file($tmp)) //permet de vérifier si le fichier a été uploadé via http
{
//vérification du type de l'img, son poids et sa taille
if ($type=="image/gif" && $size<="20500" && $width<="100" && $height<="100" )
{
// type mime gif, poids < à 20500 octets soit environ 20Ko, largeur = hauteur = 100px
//Pour supprimer les espaces dans les noms de fichiers car celà entraîne une erreur lorsque vous voulez l'afficher
$fichier = preg_replace ("` `i","",$fichier);//ligne facultative :)
//On vérifie s'il existe une image qui a le même nom dans le répertoire
if (file_exists('./images_up/'.$fichier))
{
//Le fichier existe on rajoute dans son nom le timestamp du moment pour le différencier de la première (comme cela on est sur de ne pas avoir 2 images avec le meme nom :) )
$nom_final= preg_replace("`.gif`is",date("U").".gif",$fichier);
}
else {
$nom_final=$fichier; //l'image n'existe pas on garde le même nom
}
//on déplace l'image dans le répertoire final
move_uploaded_file($tmp,'./images_up/'.$nom_final);
//Message indiquant que tout s'est bien passé
echo "L'image a été uploadée avec succès<br/>";
}
else {
//Le type mime, ou la taille ou le poids est incorrect
echo 'Votre image a été rejetée (poids, taille ou type incorrect)';
}
}

else {
echo
$retour[1],'<br />';
}
}
}
//Pour tester si l'image est bien à sa place
echo '<img src="./images_up/'.$nom_final.'" border="0" />';
echo
'<br/>';
echo
'<a href="javascript:history.back();">Retour</a>';
?>

Conclusion

Voilà avec tout cela vous avez de quoi faire un gestionnaire d'upload, sans trop de problèmes.
Rappelez-vous de toujours vérifier les informations fournies par l'utilisateur ( $_GET, $_POST, $_COOKIE, $_FILES ....) afin d'éviter au maximum les trous de sécurité.
Pour compléter vous pouvez consulter cette liste de types mime
Ceci n'est pas forcément exclu d'erreur (oublie bête) ils vous est extrement conseillé de lire et comprendre le code avant de l'utiliser !

Merci à rafaelle pour son aimable relecture et correction d'orthographe :)

Valid XHTML 1.0 Strict   Valid CSS!