Upload de fichiers en PHP

Antoine Hérault

Vous avez envie de permettre aux visiteurs de votre site d'uploader des fichiers sur votre serveur ? Mais vous ne savez pas comment faire ?
Alors ce tutoriel est fait pour vous. Vous verrez, en lisant ce tutoriel qu'uploader un fichier en php est faisable mais qu'en plus c'est très simple ! ;o)

Commentez

- Titre : Upload de fichiers en PHP

- Auteur : Antoine Hérault

- Parution : 1 décembre 2006

- Mise à jour : 1 décembre 2006

- Licence : Ce document est issu de http://www.developpez.com et reste la propriété exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur ( http://www.lahacheweb.com ).

Sommaire

- 1. Préface

- 2. Le formulaire

- 2-0. Le formulaire

- 2-1. Le champ fichier

- 2-3. Limiter la taille du fichier

- 2-4. Le formulaire complet

- 3. L'upload

- 3-0. Récupérer le fichier envoyé

- 3-1. L'upload

- 3-2. Et la sécurité

- 3-2-0. Le type de fichier

- 3-2-1. La taille maximum du fichier

- 3-2-2. Le nom du fichier

- 3-3. Le code final

- 4. Conclusion

1 - Préface

Bonjour à tous, dans cet article, vous allez apprendre à uploader un fichier grâce à un formulaire sur une page web !
L'upload est l'opération qui consiste à envoyer des informations locales (provenant de votre disque dur) sur le web. Par exemple, un tel script peut s'avérer utile pour permettre aux membres de votre site de créer leur avatar...

Le tutoriel se déroulera en 2 parties : le formulaire et l'upload.
Pour simplifier, nous allons diviser le script en deux fichiers...

2 - Le formulaire

Pour commencer, créez une page "upload.html". Cette page contiendra le formulaire.

2-0 - Le formulaire

Lorsque vous souhaitez envoyer un fichier au serveur par formulaire, vous devez préciser l'enctype, c'est à dire le type d'encodage du fichier. L'enctype à utiliser est multipart/form-data.
C'est très important car si vous ne le faites pas, vous ne pourrez pas uploader votre fichier !
Votre formulaire vide donnera donc :

Code pour ouvrir et fermer le formulaire

<form method="POST" action="upload.php" enctype="multipart/form-data">
<!-- Le contenu du formulaire est à placer ici... -->
</form>

2-1 - Le champ fichier

Pour trouver le fichier, vous devez permettre à l'utilisateur de choisir un fichier sur son disque dur.
Heureusement, HTML le fait pour nous ! ;o)
Le champ de type "file" a donc cette mission.

Code pour insérer un champ fichier

<input type="file" name="avatar">

Comme pour tous les champs de formulaire, vous devez lui donner un nom.
Je vais mettre "avatar" pour l'exemple.

2-3 - Limiter la taille du fichier

Vous aurez sûrement besoin de limiter la taille du fichier.
Il ne faudrait pas que quelqu'un s'amuse à uploader des images de plusieurs Mo...
Pour cela, vous devez utiliser un champ caché "hidden", lui donner le nom "MAX_FILE_SIZE" et lui donner en valeur, la taille maximum du fichier à uploader en octets.

Code pour limiter la taille du fichier

<input type="hidden" name="MAX_FILE_SIZE" value="100000">

2-4 - Le formulaire complet

Bon allez, je vous donne le formulaire complet :

Code final du xHTML du formulaire

<form method="POST" action="upload.php" enctype="multipart/form-data">
<!-- On limite le fichier à 100Ko -->
<input type="hidden" name="MAX_FILE_SIZE" value="100000">
Fichier : <input type="file" name="avatar">
<input type="submit" name="envoyer" value="Envoyer le fichier">
</form>

Maintenant que vous avez le formulaire en entier, vous pouvez constater que les données seront envoyées à "upload.php".
Et bien maintenant, nous allons nous occuper d'upload.php !

3 - L'upload

Bien ! Nous allons maintenant attaquer la partie la plus intéressante, à savoir l'upload.
Nous considérons que nous venons de la page upload.html.
Lorsque le formulaire a été validé, le fichier a été placé dans un dossier temporaire et sera supprimé si nous ne nous en occupons pas...

3-0 - Récupérer le fichier envoyé

Heureusement pour nous, PHP a tout prévu !
Les informations sur les fichiers envoyés sont contenues dans le tableau global $_FILES.
$_FILES contient :

NOM

VARIABLE

Le nom

$_FILES['avatar']['name']

Le chemin du fichier temporaire

$_FILES['avatar']['tmp_name']

La taille (peu fiable, dépend du navigateur)

$_FILES['avatar']['size']

Le type MIME (peu fiable, dépend du navigateur)

$_FILES['avatar']['type']

Un code d'erreur si besoin

$_FILES['avatar']['error']

3-1 - L'upload

Pour ce faire, nous allons avoir besoin de la fonction... move_uploaded_file()
Je vous laisse cliquer dessus pour voir la doc...
Cette fonction renvoie TRUE si elle a correctement fonctionné et FALSE si elle n'a pas correctement fonctionné.
Nous allons aussi avoir besoin d'un dossier, upload, auquel vous aurez généreusement au préalable accordé les droits d'écriture grâce à votre logiciel FTP.

Pour accorder les droits d'écriture, vous devez changer le CHMOD du dossier upload. Pour changer le CHMOD avec votre logiciel FTP, cliquez droit sur le dossier upload et cliquez sur "Attribut du fichier" ou "Options du CHMOD" (le nom varie selon les logiciels...). Le CHMOD que nous devons utiliser est le 755. Je vous fournirai un lien vers la FAQ expliquant le CHMOD à la fin de ce tutoriel... ;o)

Voici donc le code d'upload que je vais vous expliquer :

Code d'upload de base

<?php
if(isset($_FILES['avatar']))
{
$dossier = 'upload/';
$fichier = basename($_FILES['avatar']['name']);
if(move_uploaded_file($_FILES['avatar']['tmp_name'], $dossier . $fichier)) //Si la fonction renvoie TRUE, c'est que ça a fonctionné...
{
echo 'Upload effectué avec succès !';
}
else //Sinon (la fonction renvoie FALSE).
{
echo 'Echec de l\'upload !';
}
}
?>

Comme vous pouvez le constater, ce n'est pas bien compliqué... Je vais vous laisser cogiter sur ce code tout seuls...

3-2 - Et la sécurité

STOP! Ne mettez surtout pas ce script en ligne ! ! !

Rassurez-vous, ce n'est pas fini, ce serait trop simple sinon... Il ne faut quand même pas exagérer !

3-2-0 - Le type de fichier

Qui vous dit que l'utilisateur n'est pas en train d'uploader un fichier PHP par exemple pour tout supprimer ou récupérer le contenu de vos tables (mots de passe, adresses email...).
C'est pourquoi il faut vérifier le type du fichier que vous voulez uploader.
Voici la procédure :

Code pour vérifier le type du fichier uploadé

<?php
//On fait un tableau contenant les extensions autorisées.
//Comme il s'agit d'un avatar pour l'exemple, on ne prend que des extensions d'images.
$extensions = array('.png', '.gif', '.jpg', '.jpeg');
// récupère la partie de la chaine à partir du dernier . pour connaître l'extension.
$extension = strrchr($_FILES['avatar']['name'], '.');
//Ensuite on teste
if(!in_array($extension, $extensions)) //Si l'extension n'est pas dans le tableau
{
$erreur = 'Vous devez uploader un fichier de type png, gif, jpg, jpeg, txt ou doc...';
}
?>

Cette méthode est une première approche qui nous suffit pour le moment mais, en réalité, il faudrait vérifier le type MIME des fichiers uploadés.

3-2-1 - La taille maximum du fichier

Un utilisateur peu scrupuleux peut enregistrer le formulaire sur son disque et modifier la valeur du champ "MAX_FILE_SIZE" !
Pour remédier à cela, nous devons vérifier la taille du fichier avant de l'uploader...
Je vous rappelle que le tableau global $_FILES contient la taille du fichier mais qu'elle est peu fiable.
Heureusement, la fonction PHP filesize() retourne la taille d'un fichier en octets. Il suffit de lui donner l'adresse du fichier qui est contenue dans $_FILES['avatar']['tmp_name'] donc pas de panique...
Voici le code :

Code pour vérifier la taille du fichier

<?php
// taille maximum (en octets)
$taille_maxi = 100000;
//Taille du fichier
$taille = filesize($_FILES['avatar']['tmp_name']);
if($taille>$taille_maxi)
{
$erreur = 'Le fichier est trop gros...';
}
?>

3-2-2 - Le nom du fichier

Le nom du fichier peut lui aussi poser problème...
Nous devons donc nous occuper de lui car s'il contient des accents, caractères spéciaux, espaces, ça peut poser problème.
Nous allons donc "formater" le nom du fichier avant de l'uploader...
Il s'agit d'une expression régulière. Je ne vais pas vous expliquer les expressions régulières dans ce chapitre car il s'agit d'une chose assez difficile au début et il faudrait y consacrer au moins un cours entier.

Code pour formater le nom du fichier

<?php
$fichier = strtr($fichier,
'ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ',
'AAAAAACEEEEIIIIOOOOOUUUUYaaaaaaceeeeiiiioooooouuuuyy');
//On remplace les lettres accentutées par les non accentuées dans $fichier.
//Et on récupère le résultat dans fichier

//En dessous, il y a l'expression régulière qui remplace tout ce qui n'est pas une lettre non accentuées ou un chiffre
//dans $fichier par un tiret "-" et qui place le résultat dans $fichier.
$fichier = preg_replace('/([^.a-z0-9]+)/i', '-', $fichier);
?>

Voilà, c'est tout pour la sécurité fondamentale. ;o)

3-3 - Le code final

Voici en exclusivité, le code d'upload !

Code final de l'upload

<?php
$dossier = 'upload/';
$fichier = basename($_FILES['avatar']['name']);
$taille_maxi = 100000;
$taille = filesize($_FILES['avatar']['tmp_name']);
$extensions = array('.png', '.gif', '.jpg', '.jpeg');
$extension = strrchr($_FILES['avatar']['name'], '.');
//Début des vérifications de sécurité...
if(!in_array($extension, $extensions)) //Si l'extension n'est pas dans le tableau
{
$erreur = 'Vous devez uploader un fichier de type png, gif, jpg, jpeg, txt ou doc...';
}
if($taille>$taille_maxi)
{
$erreur = 'Le fichier est trop gros...';
}
if(!isset($erreur)) //S'il n'y a pas d'erreur, on upload
{
//On formate le nom du fichier ici...
$fichier = strtr($fichier,
'ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ',
'AAAAAACEEEEIIIIOOOOOUUUUYaaaaaaceeeeiiiioooooouuuuyy');
$fichier = preg_replace('/([^.a-z0-9]+)/i', '-', $fichier);
if(move_uploaded_file($_FILES['avatar']['tmp_name'], $dossier . $fichier)) //Si la fonction renvoie TRUE, c'est que ça a fonctionné...
{
echo 'Upload effectué avec succès !';
}
else //Sinon (la fonction renvoie FALSE).
{
echo 'Echec de l\'upload !';
}
}
else
{
echo $erreur;
}
?>

4 - Conclusion

Voilà ! ! ! C'est fini ! Vous pouvez maintenant uploader des fichiers !
J'espère que vous avez trouvé mon petit article intéressant !
Si vous trouvez des erreurs, signalez-les moi, c'est comme ça qu'on avance...
Comme promis, voici un lien vers la FAQ au sujet du CHMOD :
Le CHMOD
Maintenant que vous savez uploader des fichiers, je vous propose un tutoriel pour les gérer : Upload de fichiers en PHP
Gestionnaire de fichiers en PHP
Pour ceux qui voudraient en savoir un peu plus sur les formulaires et PHP5 :
Les formulaires et PHP5