L'upload de fichiers
L'upload de fichiers en PHP est vraiment très facile. Nous allons voir comment faire.
1- Création du formulaire html
Tout d'abord, il faut créer notre formulaire html, avec un ou plusieurs champ(s) permettant au visiteur de sélectionner un fichier sur sa machine.
Ces champs sont des champs input de type file, vous pouvez en mettre autant que vous voulez sur la page, PHP gère l'envoi multiple depuis la version 3.0.10.
Il faut également spécifier la valeur multipart/form-data dans le type d'encodage des données du formulaire (enctype).
Exemple :
< form method='POST' action='notre_script.php' enctype='multipart/form-data'>
< input type='hidden' name='MAX_FILE_SIZE' value='500000' >
< input type='file' name='p1'>< input type='file' name='p2'>
< input type='submit' name='envoi' value='Envoyer les fichiers' />
2- Gérer des fichiers envoyés avec PHP
Lorsque le formulaire est envoyé, les fichiers sont envoyés sur le serveur dans un répertoire temporaire. Une fois ces fichiers envoyés, le script php dans la partie action du formulaire est lancé. Une fois que le script php est terminé, les fichiers envoyés sont supprimés du répertoire temporaire. Il faut donc traiter/copier ces fichiers avant.
Récupérer les informations des fichiers envoyés
Les informations sur les fichiers envoyés sont accessibles depuis le tableau global $_FILES, contenant les informations suivantes :
Clef Description
name Nom original du fichier, tel que sur la machine du visiteur.
type Type MIME du fichier, si le navigateur a fourni cette information. Exemple : image/gif.
size Taille, en octets, du fichier envoyé.
tmp_name Chemin du fichier temporaire sur le serveur.
error Code d'erreur associé à l'envoi du fichier (PHP > 4.2.0).
Donc par exemple $_FILES['photo']['tmp_name'] retourne le chemin du fichier temporaire sur le serveur.
Copier les fichiers
Pour copier les fichiers envoyés dans un autre répertoire rien de plus simple, il suffit d'utiliser la fonction move_uploaded_file(). Vous devez néanmoins également donner les droits d'écriture à PHP sur le répertoire dans lequel vous souhaitez copier les fichiers. Pour cela vous pouvez par exemple utiliser la fonction CHMOD de votre logiciel FTP.
Exemple d'utilisation de move_uploaded_file :
if(isset($_FILES['p1'])){
$dest_dossier = '/photos/';
// utilisez également des slashes sous windows : $dest_dossier = 'd:/damien/photos/';
$dest_fichier = basename($_FILES['photo']['name']);
move_uploaded_file($_FILES['photo']['tmp_name'], $dest_dossier . $dest_fichier);
}
NB : N'utilisez pas ce code tel quel, lisez bien le prochain chapitre du tutorial.
3- ... mais attention !
Sécurité
Dans l'exemple précédent, le visiteur peut envoyer n'importe quel type de fichier. Rien ne l'empêche d'envoyer un fichier PHP à la pl d'une photo ! Et ensuite de l'éxecuter si le répertoire dans lequel vous stockez vos fichiers est accessible depuis le web. Il faut donc toujours penser à vérifier quel type de fichier l'utilisateur envoie, en acceptant que les fichiers ayant l'extension attendue.
// récupère la partie de la chaine à partir du dernier .
$extension = strrchr($_FILES['photo']['name'], '.');
// récupère la partie après le .
$extension = substr($extension, 1);
De plus, le visiteur peut aussi enregistrer le formulaire sur son ordinateur, et modifier la valeur du champ caché MAX_FILE_SIZE, pour ainsi envoyer des fichiers plus volumineux. Il est donc également préférable de vérifier la taille du fichier.
// récupère la taille du fichier
$taille = filesize($_FILES['photo']['tmp_name']);
Nom du fichier
Toujours dans l'exemple du chapitre précédent, on utilise le nom original de l'image (tel que sur la machine du visiteur) comme nom du fichier sur notre serveur. Cela peut poser des problèmes. Il est préférable de supprimer les accents, les espaces et les caractères spéciaux.
// enlever les accents
$dest_fichier = strtr($dest_fichier,
'ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ',
'AAAAAACEEEEIIIIOOOOOUUUUYaaaaaaceeeeiiiioooooouuuuyy');
// remplacer les caracteres autres que lettres, chiffres et point par _
$dest_fichier = preg_replace('/([^.a-z0-9]+)/i', '_', $dest_fichier);
4- Exemple
L'exemple du chapitre 2 donne donc :
if(isset($_FILES['p1'])){
unset($erreur);
$extensions_ok = array('png', 'gif', 'jpg', 'jpeg');
$taille_max = 100000;
$dest_dossier = '/photos/';
// utilisez également des slashes sous windows : $dest_dossier = 'd:/damien/photos/';
if( !in_array( substr(strrchr($_FILES['photo']['name'], '.'), 1), $extensions_ok ) ){
$erreur = 'Veuillez sélectionner un fichier de type png, gif ou jpg !';
}
elseif( file_exists($_FILES['photo']['tmp_name'])
and filesize($_FILES['photo']['tmp_name']) > $taille_max)
{
$erreur = 'Votre fichier doit faire moins de 500Ko !';
}
// copie du fichier
if(!isset($erreur)){
$dest_fichier = basename($_FILES['photo']['name']);
// formatage nom fichier
// enlever les accents
$dest_fichier = strtr($dest_fichier,
'ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ',
'AAAAAACEEEEIIIIOOOOOUUUUYaaaaaaceeeeiiiioooooouuuuyy');
// remplacer les caracteres autres que lettres, chiffres et point par _
$dest_fichier = preg_replace('/([^.a-z0-9]+)/i', '_', $dest_fichier);
// copie du fichier
move_uploaded_file($_FILES['photo']['tmp_name'], $dest_dossier . $dest_fichier);
}
}
if(isset($erreur)){
echo '', $erreur ,'';
}
'POST' action='30.php' enctype='multipart/form-data'>
'hidden' name='MAX_FILE_SIZE' value='500000' />
Envoi de fichiers
for='photo'>Photo :'file' name='photo' />
'submit' name='envoi' value='Envoyer les fichiers' />
Deux autres tutoriaux, avec des exemples plus complets (comment gérer l'envoi d'images, et un autre sur l'importation de fichier CSV) seront mis en ligne prochainement.
5- Remarques complémentaires
Envoyer des fichiers volumineux
Vous avez vu tout à l'heure que l'on peut limiter la taille des fichiers envoyés avec un champ de type hidden. Mais il existe également des options de configuration de la taille maximum dans le fichier php.ini.
* La principale option est la directive upload_max_filesize, qui permet de fixer la taille maximale d'un fichier que l'on peut envoyer (en général 2Mo par défaut).
* Mais augmenter cette valeur peut ne pas être suffisant. Il existe également la directive post_max_size pour délimiter la taille maximum des données qui peuvent être envoyées par la méthode POST (généralement 8Mo par défaut), taille des fichiers envoyés inclue. Pensez donc à modifier les deux valeurs si vous voulez permettre l'upload de fichiers volumineux.
* La directive memory_limit, si activée, peut également avoir une influence sur l'upload de fichier.
* Enfin, il faudra probablement augmenter la limite du temps d'execution de vos scripts à l'aide des directives max_execution_time et max_input_time.
Seules les directives memory_limit et max_*_time sont modifiables depuis vos scripts php :
ini_set('memory_limit', 8000000); // en octets
set_time_limit(600); // en secondes
Pour modifier les deux autres options (si vous n'avez pas accès aux fichiers php.ini ou httpd.conf), vous devez utiliser un fichier .htaccess :
php_value upload_max_filesize 5000000
php_value post_max_size 10000000
NB : Attention, pour modifier la configuration de PHP depuis un fichier .htaccess, PHP doit être installé en tant que module apache, pas en tant que CGI. Vous obtenez sinon une erreur 500.
Afficher la progression du téléchargement
Malheureusement, PHP ne permet pas d'afficher de barre de progression pendant le téléchargement. Pourquoi ? La raison est simple, le script PHP est appelé uniquement lorsque l'envoi du fichier est terminé, et ne donne pas accès aux données raw post. On ne peut donc pas controler où en est le chargement, même en utilisant du javascript.
Pas sans changement en tous cas. Il existe en effet une extension non officielle qui permet de gérer une barre de progression pendant le téléchargement. Il faut par contre appliquer un patch à PHP, et compiler l'extension. Vous ne pouvez pas le faire n'importe où (il faut pouvoir administrer le serveur), et vous devez avoir les compétences pour le faire. Le lien ci dessous n'est donc fournit qu'à titre informatif, et s'adresse aux utilisateurs avancés. A vos risques et périls.
Offline