W3docs

Téléchargement de fichiers en PHP

Apprenez à gérer l'upload de fichiers en PHP avec $_FILES et move_uploaded_file(), en validant le type MIME et la taille de façon sécurisée.

Le téléchargement de fichiers est une exigence courante dans le développement web. Qu'il s'agisse d'une photo de profil, d'un document PDF ou d'une importation CSV, permettre aux utilisateurs d'envoyer des fichiers vers votre serveur est une fonctionnalité centrale de la plupart des applications. En PHP, cela est géré par la fonction move_uploaded_file() conjointement avec le tableau superglobal $_FILES.

Ce chapitre couvre l'intégralité du processus d'upload : la configuration du formulaire HTML, la lecture des métadonnées du fichier depuis $_FILES, sa validation sécurisée, puis son déplacement vers sa destination finale. Il passe également en revue les codes d'erreur d'upload et les paramètres de configuration PHP qui contrôlent les limites d'upload.

Comment fonctionne l'upload de fichiers en PHP

Un upload de fichier se déroule en trois étapes :

  1. Le navigateur envoie le fichier dans une requête POST de type multipart/form-data.
  2. PHP reçoit le fichier et l'écrit dans un emplacement temporaire sur le disque, puis expose ses détails dans le tableau $_FILES.
  3. Votre script valide le fichier et le déplace depuis l'emplacement temporaire vers un emplacement permanent avec move_uploaded_file().

Le fichier temporaire est supprimé automatiquement à la fin de la requête si vous ne le déplacez pas, vous devez donc le traiter pendant la même requête.

Le superglobal $_FILES

Lorsqu'un fichier est uploadé, les informations le concernant sont stockées dans le tableau superglobal $_FILES. Pour un champ de formulaire nommé userfile, le tableau contient ces clés :

  • $_FILES['userfile']['name'] - Le nom original du fichier uploadé.
  • $_FILES['userfile']['type'] - Le type MIME du fichier uploadé.
  • $_FILES['userfile']['size'] - La taille du fichier uploadé en octets.
  • $_FILES['userfile']['tmp_name'] - L'emplacement temporaire du fichier uploadé sur le serveur.
  • $_FILES['userfile']['error'] - Un code d'erreur indiquant s'il y a eu un problème lors de l'upload (voir les codes d'erreur ci-dessous).

Étape 1 : Le formulaire HTML

L'attribut enctype du formulaire doit être défini à multipart/form-data, et la méthode doit être POST. Sans multipart/form-data, le navigateur envoie uniquement le nom du fichier, pas son contenu, et $_FILES sera vide.

<form action="upload.php" method="POST" enctype="multipart/form-data">
  <input type="file" name="userfile">
  <input type="submit" value="Upload">
</form>

Étape 2 : Valider l'upload

Ne faites jamais confiance à un fichier uploadé. Avant de le déplacer, vérifiez trois choses : que l'upload lui-même a réussi, que la taille est dans votre limite, et que le fichier est vraiment du type attendu.

Vérifier le code d'erreur

Inspectez toujours $_FILES['userfile']['error'] en premier. PHP définit des constantes nommées pour les valeurs possibles :

ConstanteValeurSignification
UPLOAD_ERR_OK0Aucune erreur, le fichier a été uploadé avec succès.
UPLOAD_ERR_INI_SIZE1Le fichier dépasse upload_max_filesize dans php.ini.
UPLOAD_ERR_FORM_SIZE2Le fichier dépasse le champ MAX_FILE_SIZE du formulaire.
UPLOAD_ERR_PARTIAL3Le fichier n'a été que partiellement uploadé.
UPLOAD_ERR_NO_FILE4Aucun fichier n'a été uploadé.
UPLOAD_ERR_NO_TMP_DIR6Dossier temporaire manquant.
UPLOAD_ERR_CANT_WRITE7Échec de l'écriture du fichier sur le disque.

Valider le type et la taille de façon sécurisée

Ne vous fiez pas à $_FILES['userfile']['type']. Cette valeur est fournie par le navigateur et peut être facilement falsifiée par un attaquant. À la place, détectez le vrai type MIME à partir du contenu du fichier avec l'extension finfo, et imposez vous-même une limite de taille :

$file = $_FILES['userfile'];

// 1. Did the upload succeed?
if ($file['error'] !== UPLOAD_ERR_OK) {
  exit("Upload failed with error code " . $file['error']);
}

// 2. Enforce a maximum size (2 MB here).
$maxBytes = 2 * 1024 * 1024;
if ($file['size'] > $maxBytes) {
  exit("File is too large.");
}

// 3. Detect the real MIME type, not the client-supplied one.
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime  = $finfo->file($file['tmp_name']);

$allowed = [
  'image/jpeg' => 'jpg',
  'image/png'  => 'png',
  'image/gif'  => 'gif',
];

if (!isset($allowed[$mime])) {
  exit("Only JPEG, PNG, and GIF images are allowed.");
}

Étape 3 : Déplacer le fichier vers sa destination finale

Une fois le fichier validé, déplacez-le avec move_uploaded_file(). Cette fonction prend deux arguments : le chemin temporaire ($_FILES['userfile']['tmp_name']) et le chemin de destination. Utiliser cette fonction plutôt que copy() ou rename() est important — elle vérifie que le fichier est bien un upload HTTP authentique, ce qui empêche un attaquant de tromper votre script en lui faisant déplacer un fichier arbitraire du serveur.

Générez vous-même le nom de fichier final au lieu de faire confiance au nom original. Cela évite les attaques par traversée de répertoire (un nom comme ../../config.php) et l'écrasement de fichiers existants :

$targetDir = "uploads/";

// Build a safe, unique file name; never trust the client's name.
$extension  = $allowed[$mime];
$safeName   = bin2hex(random_bytes(8)) . "." . $extension;
$targetFile = $targetDir . $safeName;

if (move_uploaded_file($file['tmp_name'], $targetFile)) {
  echo "The file was uploaded as " . $safeName;
} else {
  echo "There was an error saving the file.";
}

Pour plus de détails sur cette fonction et sa fonction complémentaire is_uploaded_file(), consultez les chapitres de référence move_uploaded_file() et is_uploaded_file().

Configuration affectant les uploads

Quelques directives php.ini limitent silencieusement ce que votre script peut recevoir. Si les uploads échouent pour des fichiers volumineux même si votre code est correct, vérifiez ces paramètres :

  • file_uploads — doit être On pour que les uploads fonctionnent.
  • upload_max_filesize — la taille maximale d'un fichier individuel que PHP acceptera (par défaut 2M).
  • post_max_size — la taille maximale du corps POST total ; doit être supérieure à upload_max_filesize.
  • max_file_uploads — le nombre maximum de fichiers dans une seule requête.

Conclusion

Les uploads de fichiers en PHP sont une partie fondamentale du développement web. Avec le tableau superglobal $_FILES et la fonction move_uploaded_file(), vous pouvez gérer les uploads en quelques lignes. La partie difficile est de le faire en toute sécurité : vérifiez toujours le code d'erreur d'upload, imposez une limite de taille, détectez le vrai type MIME avec finfo au lieu de faire confiance à $_FILES[...]['type'], et générez votre propre nom de fichier pour que le client ne puisse jamais contrôler où le fichier est stocké. Pour traiter le fichier enregistré par la suite, consultez la gestion des fichiers PHP et la validation des formulaires.

Pratique

Pratique
Lesquelles des affirmations suivantes concernant les uploads de fichiers en PHP sont correctes ?
Lesquelles des affirmations suivantes concernant les uploads de fichiers en PHP sont correctes ?
Was this page helpful?