Chargements de fichiers par méthode POST
Cette fonctionnalité permet aux personnes de télécharger à la fois du texte
et des fichiers binaires. Avec les fonctions d'identification et de
manipulation de fichiers de PHP, vous avez le contrôle total pour définir
qui a le droit de télécharger, mais aussi ce qui sera fait du fichier une
fois qu'il sera téléchargé.
PHP est capable de recevoir des fichiers émis par
un navigateur conforme à la norme RFC-1867.
Note:
Notes de configuration
Voir aussi les directives
file_uploads,
upload_max_filesize,
upload_tmp_dir,
post_max_size et
max_input_time dans php.ini
PHP supporte aussi le chargement par la méthode PUT comme dans le
navigateur Netscape Composer
et Amaya du W3C. Reportez-vous au chapitre sur le
support de la
méthode PUT.
Exemple #1 Formulaire de chargement de fichier
Un formulaire de téléchargement de fichiers peut être construit
en créant un formulaire spécifique comme ceci :
<!-- Le type d'encodage des données, enctype, DOIT être spécifié comme ce qui suit -->
<form enctype="multipart/form-data" action="_URL_" method="post">
<!-- MAX_FILE_SIZE doit précéder le champ input de type file -->
<input type="hidden" name="MAX_FILE_SIZE" value="30000" />
<!-- Le nom de l'élément input détermine le nom dans le tableau $_FILES -->
Envoyez ce fichier : <input name="userfile" type="file" />
<input type="submit" value="Envoyer le fichier" />
</form>
_URL_
dans l'exemple précédent doit être remplacé et
pointé vers un fichier PHP.
Le champ caché MAX_FILE_SIZE
(mesuré en octets) doit
précéder le champ input de type file et sa valeur représente la taille
maximale acceptée du fichier par PHP.
Cet élément de formulaire doit toujours être utilisé, car il permet
d'informer l'utilisateur que le transfert désiré est trop lourd
avant d'atteindre la fin du téléchargement. Gardez à l'esprit que
ce paramètre peut être "trompé" du côté du navigateur facilement, aussi
ne faites pas confiance à ce dernier, ne s'agissant finalement que d'une
fonctionnalité de convenance côté client. Le paramètre PHP (côté serveur)
à propos de la taille maximale d'un fichier téléchargé,
ne peut, lui, être trompé.
Note:
Assurez-vous que votre formulaire de téléchargement de fichier contienne
enctype="multipart/form-data"
, sinon,
le fichier se sera pas téléchargé.
La variable globale $_FILES va contenir toutes les
informations sur le fichier téléchargé. Son contenu est détaillé
dans notre exemple ci-dessous. Notez que l'on suppose que le nom
de la variable du fichier téléchargé est userfile, tel que
défini dans le formulaire ci-dessus, mais peut être n'importe quel nom.
-
$_FILES['userfile']['name']
-
Le nom original du fichier, tel que sur la machine du client web.
-
$_FILES['userfile']['type']
-
Le type MIME du fichier, si le navigateur a fourni cette information.
Par exemple, cela pourra être "image/gif"
.
Ce type mime n'est cependant pas vérifié du côté de PHP et, donc,
ne prend pas sa valeur pour se synchroniser.
-
$_FILES['userfile']['size']
-
La taille, en octets, du fichier téléchargé.
-
$_FILES['userfile']['tmp_name']
-
Le nom temporaire du fichier qui sera chargé sur la machine serveur.
-
$_FILES['userfile']['error']
-
Le code d'erreur
associé au téléchargement de fichier.
-
$_FILES['userfile']['full_path']
-
Le chemin entier tel que soumit par le navigateur.
Cette valeur ne contient pas toujours une vraie hiérarchie de dossier,
et il ne faut pas lui faire confiance.
Disponible à partir de PHP 8.1.0.
Le fichier téléchargé sera stocké temporairement dans le dossier
temporaire du système, à moins qu'un autre dossier soit fourni avec
la directive upload_tmp_dir du
php.ini. Le dossier par défaut du serveur peut être changé
dans l'environnement via la variable TMPDIR.
Modifier la valeur de cette variable avec la fonction putenv()
dans un script PHP sera sans effet. Cette variable d'environnement
peut aussi être utilisée pour s'assurer que d'autres opérations
fonctionnent aussi sur les fichiers téléchargés.
Exemple #2 Validation de téléchargement de fichiers
Voyez aussi les fonctions is_uploaded_file() et
move_uploaded_file() pour plus d'informations.
L'exemple suivant va télécharger un fichier venant d'un formulaire.
<?php
$uploaddir = '/var/www/uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
echo '<pre>';
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo "Le fichier est valide, et a été téléchargé
avec succès. Voici plus d'informations :\n";
} else {
echo "Attaque potentielle par téléchargement de fichiers.
Voici plus d'informations :\n";
}
echo 'Voici quelques informations de débogage :';
print_r($_FILES);
echo '</pre>';
?>
Le script PHP qui reçoit le fichier chargé doit pouvoir
gérer le fichier de manière appropriée. Vous
pouvez utiliser la variable $_FILES['userfile']['size'] pour recaler
tous les fichiers qui sont trop gros ou trop petits. Vous pouvez utiliser
la variable $_FILES['userfile']['type'] pour écarter
les fichiers qui n'ont pas le bon type, mais l'utiliser uniquement pour une série de
vérifications, car cette valeur est complètement sous le contrôle du client
et n'est pas vérifiée du côté de PHP.
Vous pouvez utiliser l'information dans
$_FILES['userfile']['error'] et adapter votre politique
en fonction des codes d'erreur.
Quelle que soit votre politique, vous devriez soit effacer le fichier du
dossier temporaire, soit le déplacer.
Si aucun fichier n'est sélectionné dans le formulaire, PHP retournera
0
dans $_FILES['userfile']['size']
et rien du tout dans $_FILES['userfile']['tmp_name'].
Le fichier sera automatiquement effacé du dossier temporaire
à la fin du script, s'il n'a pas été déplacé ou renommé.
Exemple #3 Envoi d'un tableau de fichiers
PHP supporte les tableaux en HTML
ainsi qu'avec les fichiers.
<form action="" method="post" enctype="multipart/form-data">
<p>Images:
<input type="file" name="pictures[]" />
<input type="file" name="pictures[]" />
<input type="file" name="pictures[]" />
<input type="submit" value="Send" />
</p>
</form>
<?php
foreach ($_FILES["pictures"]["error"] as $key => $error) {
if ($error == UPLOAD_ERR_OK) {
$tmp_name = $_FILES["pictures"]["tmp_name"][$key];
// basename() peut empêcher les attaques "filesystem traversal";
// une autre validation/nettoyage du nom de fichier peux être appropriée
$name = basename($_FILES["pictures"]["name"][$key]);
move_uploaded_file($tmp_name, "data/$name");
}
}
?>
La barre de progression de téléchargement peut être implémentée en utilisant la progression du chargement via les sessions.