Pour uploader un fichier en PHP, de manière sécurisée, vous devez:
- Utiliser une variable de serveur et d'exécution pour définir l'url et le nom de la page PHP.
- Vérifier si le fichier a été téléchargé par HTTP
POST
.
- Contrôler l'extension du fichier à uploader.
- Contrôler type de contenu MIME du fichier à uploader.
- Vérifier la taille du fichier.
- Sécuriser le nom du fichier.
- Vérifier l'existence du répertoire de destination.
- Vérifier les droits en écriture du répertoire.
- Vérifier si un fichier portant le même nom existe déjà.
Voici un exemple de script d'upload de fichier, en PHP, qui reprend les éléments ci-avant :
<?php
error_reporting(E_ALL);
ini_set("display_errors", 1);
// Configuration
// Chemin d'accès relatif vers le répertoire d'upload
$conf_repertoire = "test/";
// Extensions autorisées
$conf_extensions = array('pdf','jpg','png');
// Mime autoriées
$conf_mime = array('application/pdf','image/jpeg','image/png');
// Taille maximum des fichiers en octets
$conf_taille_max = 50000000;
// Nom du fichier sur le serveur
// 0 = nom d'origine
// 1 = nom généré de manière aléatoire
// 2 = nom fixe
$conf_nom_type = 1;
// Si choix 2, quel est le nom prédéfini
$conf_nom_fixe = "fichier";
// Quelques fonctions utiles
// Fonction pour générer un nom de fichier non prédictible, au hasard
function hasard(int $longueur = 64 ,string $caracteres = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'): string
{
if ($longueur < 1)
{
throw new \RangeException("La longueur doit être positive");
}
$pieces = [];
$max = mb_strlen($caracteres, '8bit') - 1;
for ($i = 0; $i < $longueur; ++$i)
{
$pieces [] = $caracteres[random_int(0, $max)];
}
return implode('', $pieces);
}
// Fonction de sécurisation du nom du fichier
function securisation_fichier($fichier)
{
$fichier = trim($fichier);
$fichier = stripslashes($fichier);
$fichier = htmlspecialchars($fichier);
return $fichier;
}
// On définit les variables nécessaires
$erreur = "";
$succes = "";
// Traitement et upload du fichier
if ($_SERVER["REQUEST_METHOD"] == "POST")
{
if ((isset($_FILES["fichier"])) && ($_FILES['fichier']['error'] == UPLOAD_ERR_OK))
{
$fichier_nom_origine = $_FILES['fichier']['name'];
$fichier_nom_temporaire = $_FILES['fichier']['tmp_name'];
$fichier_extension= strtolower(pathinfo($fichier_nom_origine, PATHINFO_EXTENSION));
$fichier_mime = mime_content_type($_FILES['fichier']['tmp_name']);
if (is_uploaded_file($fichier_nom_temporaire))
{
if ($conf_nom_type == 0)
{
$fichier_nom_definitif = securisation_fichier($fichier_nom_origine);
}
else if ($conf_nom_type == 1)
{
$fichier_nom_definitif = securisation_fichier(hasard());
}
else if ($conf_nom_type == 2)
{
$fichier_nom_definitif = securisation_fichier($conf_nom_fixe);
}
else $erreur .= "Nom du fichier non défini<br>";
if (!in_array($fichier_extension, $conf_extensions))
{
$erreur .= "Extension du fichier non valide<br>";
}
if (!in_array($fichier_mime, $conf_mime))
{
$erreur .= "Mime du fichier non valide<br>";
}
if ((($_FILES['fichier']['size']) > $conf_taille_max) || (($_FILES['fichier']['size']) < 0))
{
$erreur .= "Taille du fichier non valide<br>";
}
if (!is_dir(dirname($conf_repertoire)))
{
$erreur .= "Le répertoire de destination n'existe pas<br>";
}
if (!is_writable(dirname($conf_repertoire)))
{
$erreur .= "Le répertoire de destination ne dispose pas des droits en écriture<br>";
}
if (file_exists($conf_repertoire.$fichier_nom_definitif.".".$fichier_extension))
{
$erreur .= "Un fichier avec le même nom existe déja<br>";
}
}
if ($erreur == "")
{
if ($conf_nom_type == 0)
{
if (move_uploaded_file($fichier_nom_temporaire, $conf_repertoire.$fichier_nom_definitif))
{
$succes .= "Fichier envoyé avec succès";
}
}
else
{
if (move_uploaded_file($fichier_nom_temporaire, $conf_repertoire.$fichier_nom_definitif.".".$fichier_extension))
{
$succes .= "Fichier envoyé avec succès";
}
}
}
}
}
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Comment uploader un fichier en PHP de manière sécurisée</title>
</head>
<body>
<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>" method="post" enctype="multipart/form-data">
<input type="file" name="fichier">
<input type="submit" value="Upload">
</form>
<p><?php echo $erreur.$succes;?></p>
</body>
</html>
Remarque : Il est également conseillé de scanner le fichier à la recherche de virus avant d'effectuer l'upload. Pour ce faire vous devez utiliser une API ; à titre d'exemple CloudMersive.