Comment uploader un fichier vers son site via http ?
Comme ça revient très souvent sur les forums voici un tutoriel 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.
Le
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 tutoriel les codes sont écrits pour la configuration suivante :
- Short tags = Off
- Registers globals = Off
Dans traitement.php nous récupérons les informations de notre fichier dans un tableau super global $_FILES ! celui ci contient :
- name : le nom de l'image sur l'ordinateur du client
- tmp_name : le nom temporaire de l'image sur le serveur (depuis la racine du disque)
- size : la taille en octets du fichier
- type : le type mime du fichier sélectionné par le client
- error : l'erreur rapportée par php lors de l'upload de l'image
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="fichie[]" 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 :
- 0 : pas d'erreur
- 1 : le fichier dépasse la taille maximale d'upload autorisée par le webmestre (avec le champ caché MAXFILESIZE)
- 2 : Votre fichier dépasse la taille maximale demandée par le Webmestre
- 3 : fichier pas totalement uploadé sur le serveur
- 4 : aucun fichier téléchargé
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 UPLOAD_ERR_OK : $erreur = 'Pas d'erreur';$valid = true;break;
case UPLOAD_ERR_INI_SIZE : $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 UPLOAD_ERR_FORM_SIZE : $erreur = 'Votre fichier dépasse la taille maximale demandée par le Webmestre';$valid = false;break;
case UPLOAD_ERR_PARTIAL : $erreur = 'Le fichier n'a été que partiellement téléchargé. !!!';$valid = false;break;
case UPLOAD_ERR_NO_FILE : $erreur = 'Aucun fichier téléchargé !!!';$valid = false;break;
case UPLOAD_ERR_NO_TMP_DIR : $erreur = 'Un dossier temporaire est manquant.'
case UPLOAD_ERR_CANT_WRITE : $erreur = 'Échec de l'écriture du fichier sur le disque.'
case UPLOAD_ERR_EXTENSION : $erreur = 'Une extension PHP a arrété l'envoi de fichier. PHP ne propose aucun moyen de déterminer quelle extension est en cause. L'examen du phpinfo() peut aider.';
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 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)';
}
}
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
Ou celle-ci
Ceci n'est pas forcément exempt d'erreur (oublie bête) ils vous est extrêmement conseillé de lire et comprendre le code avant de l'utiliser !
Merci à rafaelle pour son aimable relecture et correction d'orthographe :)