Nous voilà donc plongés dans le vif du sujet !
Pour commencer, reprenons notre formulaire. Nous avons appelé la page
news.php, mais il s'agit en fait de la page que vous utilisez pour traiter en PHP votre formulaire de news. O.K. ? Donc, vous l'appelez comme bon vous semble.
Dans ce tutoriel, je décide de n'accepter que les images au format JPEG, mais je vous montre quand même l'utilisation d'autres formats.
On y va : on récupère notre fichier image envoyé par la méthode
POST.
Code : PHP | <?php
if (!empty($_FILES['ImageNews']))
{
if ($_FILES['ImageNews']['error'] <= 0)
{
if ($_FILES['ImageNews']['size'] <= 2097152)
{
$ImageNews = $_FILES['ImageNews']['name'];
?>
|
Ça va jusque-là ? N'oubliez pas qu'il fallait s'assurer de ne pas dépasser un poids maximal de 2 Mo pour l'image (soit 2 097 152 octets), même s'il possède une valeur par défaut.
Passons au premier exercice.
Premier exercice : fixer les extensions autorisées des images à uploader
Nous désirons accepter les extensions suivantes (parce que je suis généreux

) :
- .jpg ;
- .JPG ;
- .jpeg ;
- .JPEG ;
- .gif ;
- .GIF ;
- .png ;
- .PNG.
Vous pouvez bien entendu ajouter ce que vous voulez, dans la mesure où vous réfléchissez ensuite à la manière de traiter vos images, en utilisant les fonctions adéquates.
Comment faire pour s'assurer que l'extension du fichier à uploader est bien une de celles acceptées ?
Je vous laisse y réfléchir un peu…
Vous avez trouvé ?
Code : PHP | <?php
// Je crée un array dans lequel figurent seulement les extensions acceptées, avec le type MIME qui leur est associé (qui peut varier sous IE et qu'on va donc devoir différencier) :
$ListeExtension = array('jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'png' => 'image/png', 'gif' => 'image/gif');
$ListeExtensionIE = array('jpg' => 'image/pjpg', 'jpeg'=>'image/pjpeg'); // Il fallait une nouvelle fois qu'IE se différencie.
?>
|
Le principe est simple : je crée un tableau d'équivalences dans lequel je précise les extensions que j'accepte avec le type MIME associé en fonction du navigateur, car le type MIME d'un fichier JPEG (et seulement ce format-là) peut être interprété différemment sous IE… Il fallait bien qu'il se distingue une fois de plus, celui-là.
Si l'extension de mon fichier est contenue dans l'array, tout est O.K. et on continue, sinon on indique qu'une erreur s'est produite.
Deuxième exercice : vérifier l'extension de notre fichier en utilisant nos array précédents
Idem, je vous laisse deux minutes pour réfléchir.
Attention : 3… 2… 1… partez !
Code : PHP | <?php
// Je vérifie l'extension présumée du fichier :
$ExtensionPresumee = explode('.', $ImageNews);
$ExtensionPresumee = strtolower($ExtensionPresumee[1]);
if ($ExtensionPresumee == 'jpg' || $ExtensionPresumee == 'jpeg' || $ExtensionPresumee == 'pjpg' || $ExtensionPresumee == 'pjpeg' || $ExtensionPresumee == 'gif' || $ExtensionPresumee == 'png')
{
// On pourra alors continuer notre vérification.
?>
|
Explications
J'utilise ma première fonction :
explode. Je découpe donc
$ImageNews en deux chaînes, de part et d'autre du délimiteur «
. » (le point) ; l'une s'appelle
$ExtensionPresumee et contient le nom de l'image (située avant le point), l'autre contient l'extension (située après le point). Puis je choisis uniquement de m'intéresser à la chaîne contenant l'extension ; elle est appelée par
$ExtensionPresumee[1] (c'est bien la deuxième chaîne puisque la numérotation d'un array commence à 0 : vous vous en souvenez ?).
Ensuite, je convertis cette extension en minuscules grâce à
strtolower, pour éviter les conflits de reconnaissance entre .jpg et .JPG, ou entre .jpeg et .JPEG (ou .GIF et .gif, etc.).
Enfin, je vérifie que
$ExtensionPresumee correspond bien à l'une des extensions acceptées.
Mais attention ! Les plus malins me diront :
Citation : Les plus malins… et si je nomme mon image
mon.image.jpg ?
L'
explode me renvoiera
image comme extension ! Et ce n'est pas une extension valide.

Bonne remarque effectivement, et merci à
samuel2202 de m'avoir soumis cette proposition de rectification.
On va donc contourner le problème en comptabilisant (grâce à la fonction
count) le nombre d'entrées de l'array retourné par l'
explode, et en enlevant 1 au nombre total.

En effet, je rappelle que la numérotation des chaînes débute à 0. S'il y a 4 chaînes retournées, la dernière sera donc la
[3] (4 - 1 !).
Voici alors le code rectifié :
Code : PHP | <?php
$ExtensionPresumee = explode('.', $ImageNews);
$ExtensionPresumee = strtolower($ExtensionPresumee[count($ExtensionPresumee)-1]);
if ($ExtensionPresumee == 'jpg' || $ExtensionPresumee == 'jpeg' || $ExtensionPresumee == 'pjpg' || $ExtensionPresumee == 'pjpeg' || $ExtensionPresumee == 'gif' || $ExtensionPresumee == 'png')
{
// On pourra alors continuer notre vérification.
?>
|
On poursuit ?
Troisième exercice : vérifier que le type MIME de l'image correspond bien à son extension
Petit rappel : le type MIME, défini depuis 1991, correspond à une information relative au fichier transféré par protocole HTTP ou par mail. En d'autres termes, lors d'une transaction entre le serveur et le navigateur, le serveur envoie en premier à votre navigateur le type MIME du fichier envoyé.
Je vous demande donc maintenant de vérifier que le type MIME de l'image que vous avez choisie correspond bien à son extension, de façon à éviter des erreurs d'affichage.

C'est de la fonction
getimagesize dont vous aurez besoin.
Attention, à vos touches, prêts ? Tapez !
…
…
…
Là, vous êtes un peu longs.

Fini ? Non ? Pas trouvé ?
Alors…
Code : PHP | <?php
$ImageNews = getimagesize($_FILES['ImageNews']['tmp_name']);
if($ImageNews['mime'] == $ListeExtension[$ExtensionPresumee] || $ImageNews['mime'] == $ListeExtensionIE[$ExtensionPresumee])
{
?>
|
Explications
- On utilise la fonction getimagesize pour déterminer le type MIME de l'image, en se basant toujours sur le nom temporaire de l'image uploadée.
- On vérifie que le type MIME de l'image correspond à un type répertorié, en fonction du navigateur qui renvoie le type :
(si le navigateur est MF)
Code : PHP | <?php if($ImageNews['mime'] == $ListeExtension[$ExtensionPresumee])?>
|
(si le navigateur est IE)
Code : PHP | <?php if($ImageNews['mime'] == $ListeExtensionIE[$ExtensionPresumee])?>
|
Facile, non ?
Je vous vois d'ici me dire :
Citation : Vous… il est bien gentil lui, mais jusque-là on n'a toujours pas redimensionné notre image !
Pas de panique, on y arrive. Par contre, à partir de là, et comme ce dossier doit rester un tutoriel, je ne vous exposerai que la façon de redimensionner une image au format JPEG. Il vous faudra donc, si vous voulez utiliser une image PNG ou GIF, faire un petit effort de relecture et d'adaptation (eh oui, je ne peux pas toujours vous mâcher le travail

).
Quatrième exercice : créons notre copie d'image à redimensionner
Pour utiliser une image en vue de la redimensionner, il faut en créer une « sauvegarde », ici grâce à la fonction
imagecreatefromjpeg.
Vous souvenez-vous des explications de la partie 2 ?
Vous devrez vous servir du nom temporaire de l'image, récupéré par $_FILES, pour créer votre sauvegarde, et à condition que toutes les conditions précédentes aient été remplies.
Sur ces mots, je vous laisse réfléchir, mes amis…
Code : PHP | <?php
$ImageChoisie = imagecreatefromjpeg($_FILES['ImageNews']['tmp_name']);
?>
|
Explications
- On récupère le nom temporaire de l'image que l'on a choisie au départ : $_FILES['ImagesNews']['tmp_name'].
- On lui applique la fonction imagecreatefromjpeg : imagecreatefromjpeg ($_FILES['ImageNews']['tmp_name']).
Rappel : si votre image est au format PNG, vous appliquerez imagecreatefrompng.
Bravo, vous venez de sauvegarder votre image.
Passons à la suite : il nous faut déterminer les dimensions de notre première image pour pouvoir jouer dessus et redimensionner notre copie.
Cinquième exercice : récupérer les dimensions de l'image de départ
Quelle est la fonction qui permet de récupérer les dimensions d'un fichier posté ?
getimagesize, bravo !

N'oubliez pas : nous travaillons toujours sur le nom temporaire de l'image choisie (
$_FILES['ImageNews']['tmp_name']), et vous appellerez la nouvelle variable correspondant à la taille de l'image
$TailleImageChoisie (par exemple).
Vous avez une minute montre en main…
Code : PHP | <?php
$TailleImageChoisie = getimagesize($_FILES['ImageNews']['tmp_name']);
?>
|
Bon, là il n'y a pas grand-chose à expliquer… Tout est clair, non ?
Eh bien ! Vous avez fait du chemin d'un coup !
Récapitulons :
- vous avez créé une copie de votre image ;
- vous avez défini ses dimensions.
Il nous faut donc maintenant préciser les nouvelles dimensions que nous souhaitons appliquer à la future image (celle qui sera redimensionnée).
Sixième exercice : tailler la nouvelle image
Plusieurs choix s'offrent ici à nous :
- créer une image dont largeur et hauteur seront les mêmes (déformations assurées
) ;
- déterminer séparément la nouvelle hauteur et la nouvelle largeur (perte de temps) ;
- ou définir une nouvelle largeur et déterminer la hauteur qui lui est proportionnelle.
Mais pour cela il faudra, avant de pouvoir afficher la hauteur proportionnellement à la largeur, trouver le ratio largeur / hauteur de la première image, pour l'appliquer ensuite à la nouvelle taille.
Quelles fonctions allez-vous utiliser ?
Aucune !

C'était un piège… Il nous suffira d'effectuer des calculs très simples.
Au boulot, jeunes gens.
Code : PHP | <?php
// Étape 1 :
$NouvelleLargeur = 350;
// Étape 2 :
$Reduction = ( ($NouvelleLargeur * 100)/$TailleImageChoisie[0] );
// Étape 3 :
$NouvelleHauteur = ( ($TailleImageChoisie[1] * $Reduction)/100 );
?>
|
Explications
- Étape 1 : je définis « en dur » la largeur de ma future image. Ici, j'opte pour une largeur de 350 px.
- Étape 2 : je calcule le pourcentage de réduction qui correspond au quotient de l'ancienne largeur par la nouvelle. Comme c'est un pourcentage, on multiplie le résultat par 100.

- Étape 3 : enfin, je détermine la hauteur de la nouvelle image en appliquant le pourcentage de réduction à l'ancienne hauteur. Vous vous souvenez ? Le premier paramètre de getimagesize définit la hauteur de l'image.
N'oubliez pas de diviser par 100 pour convertir en véritable valeur « dimension », sinon vous resterez en valeur « pourcentage » à cause de la réduction.
Créons tout de suite la nouvelle image en lui appliquant ses nouvelles dimensions, que nous venons de trouver.
Septième exercice : création de la miniature
Alors, comment s'y prendre ?
Revenons un instant sur la liste des fonctions que nous devions utiliser :
- explode ;
- strtolower ;
- imagecreatefromjpeg ;
- getimagesize ;
- imagecreatetruecolor ;
- imagecopyresampled ;
- imagedestroy ;
- imagejpeg.
Vous avez déjà intégré dans votre script les quatre premières. Nous nous servirons au cours de cet exercice des deux suivantes :
imagecreatetruecolor et
imagecopyresampled (nous parlerons des deux dernières un peu plus tard).
Rappels : la fonction
imagecreatetruecolor doit être appelée après la fonction
imagecreatefromjpeg, tandis que la fonction
imagecopyresampled sert à ré-échantillonner l'image de départ en la nouvelle image désirée.
Donc, d'abord
imagecreatetruecolor, puis
imagecopyresampled.
Vous devriez avoir déjà fini !

Que faites-vous à attendre, là ? Codez !
Code : PHP | <?php
//Etape 1 :
$NouvelleImage = imagecreatetruecolor($NouvelleLargeur , $NouvelleHauteur) or die ("Erreur");
//Etape 2 :
imagecopyresampled($NouvelleImage , $ImageChoisie, 0, 0, 0, 0, $NouvelleLargeur, $NouvelleHauteur, $TailleImageChoisie[0],$TailleImageChoisie[1]);
?>
|
Explications
- Étape 1 : les paramètres d'imagecreatetruecolor entre parenthèses sont faciles à comprendre : je veux créer une nouvelle image de largeur $NouvelleLargeur et de hauteur $NouvelleHauteur. J'ai mis un die pour que l'on soit au courant si une erreur se produit.
- Étape 2 : on ré-échantillonne la nouvelle image en précisant des paramètres qui doivent vous laisser perplexes.
On place d'abord entre les parenthèses la variable qui correspond à notre image redimensionnée ($NouvelleImage), puis on indique celle que l'on a utilisée ($ImageChoisie). Ensuite, on indique la position relative de la nouvelle image en précisant les éventuels décalages que l'on veut lui attribuer : ici, j'ai choisi de ne rien décaler, donc j'ai mis 0, 0, 0, 0 pour caler les deux images aux mêmes coordonnées (abscisses et ordonnées). Puis on précise les nouvelles dimensions de la future image $NouvelleLargeur et $NouvelleHauteur. Enfin, il ne faut pas oublier de préciser les dimensions de l'ancienne image ($TailleImageChoisie[0] (= la largeur), $TailleImageChoisie[1] (= la hauteur)).
Eh bien mes amis, nous en avons presque fini avec le redimensionnement de notre image.
Pourquoi conserver l'image initiale, alors qu'elle ne nous sert plus à rien ?
Bonne question. La réponse est simple : vous pouvez vous en servir pour l'afficher en taille « réelle » lorsque votre miniature est une image cliquable (exemple d'un diaporama).
Ici, il n'y a donc qu'une chose à faire : la supprimer, puisque nous ne nous servirons pas d'images cliquables dans mon exemple.
Allez, encore quelques efforts de mémoire.
Quelle fonction nous permet de supprimer un fichier image dont on ne veut plus ?
imagedestroy, bravo !
Vous souvenez-vous de la copie sauvegardée de notre image ? Celle que l'on a nommée
$ImageChoisie, et que l'on a obtenue grâce à la fonction
imagecreatefromjpeg ?
Eh bien, vous allez vous en servir, parce que c'est elle qu'il faut supprimer !
Allez, je vous attends…
Code : PHP | <?php
imagedestroy($ImageChoisie);
?>
|
Résumons un peu, maintenant.
Nous avons choisi une image à redimensionner, déterminé ses dimensions, créé une copie sauvegardée de cette image, redimensionné l'image comme voulu, ré-échantillonné l'image pour pouvoir l'utiliser, et détruit l'image choisie au départ pour éviter de surcharger le serveur.
Notre travail est donc terminé. Youpi !
Mais les plus attentifs me diront que nous n'avons pas utilisé la fonction
imagejpeg dont nous avions parlé dans la seconde sous-partie. Elle n'intervient pas dans le redimensionnement mais dans l'enregistrement du fichier dans un dossier spécifique. Et comme je suis très gentil, je vais vous montrer en bonus comment utiliser cette dernière fonction et ainsi enregistrer notre image redimensionnée dans un dossier précis de votre serveur.
Bonus : enregistrer notre nouvelle image grâce à imagejpeg
Nous allons suivre ici la logique adoptée depuis le début, mais nous allons en plus sécuriser le nom de l'image grâce à une fonction supplémentaire. Le but de cette démarche sera d'éviter les doublons de noms lors de l'insertion et d'éviter les problèmes de sécurité liés à la conservation du nom de l'image lors de l'envoi.
Retrouver le nom de l'image en utilisant explode
Une nouvelle fois,
explode va se montrer fort utile. Tout ce que nous voulons, c'est supprimer (provisoirement) l'extension de notre image pour ne conserver que son nom. Alors, c'est du gâteau, n'est-ce pas ?
Je pars du principe que je modifie le nom original de l'image de départ, récupérée par $_FILES, et que j'ai nommée au début $ImageNews.
Code : PHP | <?php
$NomImageChoisie = explode('.', $ImageNews);
?>
|
Modifier le nom retrouvé pour sécuriser notre insertion
Je crée donc une variable
$NomImageExploitable, correspondant au nom définitif de mon image. C'est cette variable qui sera « cryptée » numériquement. Pour cela il faudra, par exemple, utiliser la fonction
time() (mais la fonction
microtime() peut également être utilisée

).
Code : PHP | <?php
$NomImageExploitable = time();
?>
|
Petite explication au passage
Il est préférable, pour alléger le code, d'écrire ceci :
Code : PHP | <?php
$NomImageExploitable = time();
?>
|
plutôt que cela :
Code : PHP | <?php
$NomImageExploitable = time($NomImageChoisie[0]);
|
puisque le nom original de l'image ne nous sert ici plus à rien (ben oui, on le « crypte »

).
Finir en enregistrant la nouvelle image dans le dossier de notre choix, tout en choisissant sa qualité
C'est ici que nous allons utiliser notre dernière fonction,
imagejpeg, en stipulant le nom de la variable contenant la nouvelle image (
$NouvelleImage), la dénomination de celle-ci (
$NomImageExploitable) et son extension (
$ExtensionPresumee), et finalement la qualité de ré-échantillonnage (valeur numérique de 0 à 100).
Code : PHP | <?php
imagejpeg($NouvelleImage , 'imagesnews/'.$NomImageExploitable.'.'.$ExtensionPresumee, 100);
?>
|
Explications
J'ai choisi un dossier fictif nommé
imagesnews. Je détermine l'extension de mon image redimensionnée grâce au paramètre de l'array
$ExtensionPresumee.
Je l'enregistre avec une
qualité de 100 (qualité maximale). Mais bien souvent, une valeur de 80 suffit amplement.
Voilà, votre image redimensionnée est enregistrée dans le dossier
imagesnews, avec une qualité de 100, et des dimensions choisies.
Pour finir, une petite devinette.
Comment insérer un lien relatif dans ma BDD, et récupérer cette image facilement dans mes news ?
Je crée une variable
$LienImageNews qui aura pour valeur le chemin relatif vers la nouvelle image :
Code : PHP | <?php
$LienImageNews = 'imagesnews/'.$NomImageExploitable.'.'.$ExtensionPresumee;
?>
|
puis je l'insère dans ma page.
Extra-bonus : code possible pour l'utilisation d'une image JPEG
N'oubliez pas de vous référer au code de notre formulaire d'insertion de la première sous-partie pour comprendre l'utilisation des variables. J'évite volontairement la connexion à la BDD, parce que chacun a sa propre méthode (en dur dans le code, en
include…).
Code : PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 | <?php
if (!empty($_POST['InsererNews']))
{
$ListeExtension = array('jpg' => 'image/jpeg', 'jpeg'=>'image/jpeg');
$ListeExtensionIE = array('jpg' => 'image/pjpeg', 'jpeg'=>'image/pjpeg');
if (!empty($_POST['TitreNews']) && (!empty($_FILES['ImageNews'])) && (!empty($_POST['ContenuNews'])))
{
$TitreNews = $_POST['TitreNews'];
$ContenuNews = $_POST['ContenuNews'];
if ($_FILES['ImageNews']['error'] <= 0)
{
if ($_FILES['ImageNews']['size'] <= 2097152)
{
$ImageNews = $_FILES['ImageNews']['name'];
$ExtensionPresumee = explode('.', $ImageNews);
$ExtensionPresumee = strtolower($ExtensionPresumee[count($ExtensionPresumee)-1]);
if ($ExtensionPresumee == 'jpg' || $ExtensionPresumee == 'jpeg')
{
$ImageNews = getimagesize($_FILES['ImageNews']['tmp_name']);
if($ImageNews['mime'] == $ListeExtension[$ExtensionPresumee] || $ImageNews['mime'] == $ListeExtensionIE[$ExtensionPresumee])
{
$ImageChoisie = imagecreatefromjpeg($_FILES['ImageNews']['tmp_name']);
$TailleImageChoisie = getimagesize($_FILES['ImageNews']['tmp_name']);
$NouvelleLargeur = 350; //Largeur choisie à 350 px mais modifiable
$NouvelleHauteur = ( ($TailleImageChoisie[1] * (($NouvelleLargeur)/$TailleImageChoisie[0])) );
$NouvelleImage = imagecreatetruecolor($NouvelleLargeur , $NouvelleHauteur) or die ("Erreur");
imagecopyresampled($NouvelleImage , $ImageChoisie , 0,0, 0,0, $NouvelleLargeur, $NouvelleHauteur, $TailleImageChoisie[0],$TailleImageChoisie[1]);
imagedestroy($ImageChoisie);
$NomImageChoisie = explode('.', $ImageNews);
$NomImageExploitable = time();
imagejpeg($NouvelleImage , 'imagesnews/'.$NomImageExploitable.'.'.$ExtensionPresumee, 100);
$LienImageNews = 'imagesnews/'.$NomImageExploitable.'.'.$ExtensionPresumee;
$sql= 'INSERT INTO votre_table VALUES ("", "'.$TitreNews.'", "'.$ContenuNews.'", "'.$LienImageNews.'", "'.time().'")';
$res = mysql_query($sql) or die(mysql_error());
if ($res)
{
echo 'La news a bien été insérée';
}
}
else
{
echo 'Le type MIME de l\'image n\'est pas bon';
}
}
else
{
echo 'L\'extension choisie pour l\'image est incorrecte';
}
}
else
{
echo 'L\'image est trop lourde';
}
}
else
{
echo 'Erreur lors de l\'upload image';
}
}
else
{
echo 'Au moins un des champs est vide';
}
}
?>
|
Notez que je n'ai pas sécurisé les données ! J'ai effectué une simple vérification des données concernant l'image. Il vous faudra vérifier les autres variables.
Par exemple, passez
$TitreNews,
$ContenuNews par un
mysql_real_escape_string,
htmlspecialchars et
trim, vérifiez que le nom de vos fichiers ne contienne pas d'espaces superflues qui pourraient bloquer la vérification, etc.
De plus,
il vous faudra assurer la connexion à votre base de données.
