Stocker des images sous MySQL avec PHP

NB : Cet article est un ancien tutoriel datant d’il y a déjà quelques années

Avant tout chose, il faut que vous sachiez que cette méthode est très lourde. Je vous la présente principalement pour le fun si vous ne savez pas quoi faire de votre temps.

  • Le principal inconvénient est que ces images prennent de la place dans notre base de données. Elles vont considérablement l’alourdir.
  • Deuxièmement, comme elles sont stockées dans notre base, pour les afficher, il faut faire appel à une requête. Donc ralentissement considérable de votre site.
  • Perte de l’arborescence

Script et principe

Voici la structure de la table avec laquelle nous allons travailler.

1
2
3
4
5
6
7
8
CREATE TABLE `images` (
   `id_img` INT NOT NULL AUTO_INCREMENT,
   `nom` VARCHAR(50) NOT NULL,
   `description` text NOT NULL,
   `img` BLOB NOT NULL,
   `extension` VARCHAR(25) NOT NULL,
   PRIMARY KEY (`id_img`);
)

Je ne pense pas qu’il y ait de problème de compréhension, sauf sur un point peut-être : le champ de type BLOB. Le type BLOB, ou Binary Large OBject, est un type de donnée permettant le stockage de données binaires.

Le formulaire : page traitement.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
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" >
   <head>
       <title>Envoyer une image</title>
       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
	   <style type="text/css">
		label {
			display:block;
			width:150px;
			float:left;
		}
	   </style>
   </head>
   <body>
	<h1>Envoyer une image</h1>
	<form enctype="multipart/form-data" action="traitement.php" method="post">
		<p>
			<label for="nom">Nom : </label><input type="text" name="nom" id="nom" /><br />
			<label for="description">Description : </label><textarea name="description" id="description" rows="10" cols="50"></textarea><br />
			<label for="image">Image : </label><input type="file" name="image" id="image" /><br />
			<label for="validation">Valider : </label><input type="submit" name="validation" id="validation" value="Envoyer" />
		</p>
	</form>
</body>
</html>

Ce code nous donne l’aperçu suivant :

Exemple formulaire upload

Formulaire d'upload

La partie enctype= »multipart/form-data » est celle qui permet d’indiquer que l’on souhaite uploader un fichier.
Ensuite, il suffit de rajouter un champ de saisie de type file comme ceci :

1
<input type="file" name="image" />

Il permet l’affichage de la boîte Parcourir pour chercher une image (ou un autre fichier) sur notre ordinateur.

Le traitement

Maintenant que l’on a le formulaire, il faut faire le traitement. Nous le ferons dans la même page, mais vous pouvez le séparer sur une seconde page, bien évidemment. Nous l’intégrerons juste après la balise body.

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
74
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" >
   <head>
       <title>Envoyer une image</title>
       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
	   <style type="text/css">
		label {
			display:block;
			width:150px;
			float:left;
		}
	   </style>
   </head>
   <body>
 
<?php
  if(isset($_POST['validation'])) {
 
	 //Indique si le fichier a été téléchargé
	 if(!is_uploaded_file($_FILES['image']['tmp_name']))
		echo 'Un problème est survenu durant l opération. Veuillez réessayer !';
	 else {
		//liste des extensions possibles    
		$extensions = array('/png', '/gif', '/jpg', '/jpeg');
 
		//récupère la chaîne à partir du dernier / pour connaître l'extension
		$extension = strrchr($_FILES['image']['type'], '/');
 
		//vérifie si l'extension est dans notre tableau            
		if(!in_array($extension, $extensions))
			echo 'Vous devez uploader un fichier de type png, gif, jpg, jpeg.';
		else {         
 
			//on définit la taille maximale
			define('MAXSIZE', 300000);        
			if($_FILES['image']['size'] > MAXSIZE)
			   echo 'Votre image est supérieure à la taille maximale de '.MAXSIZE.' octets';
			else {
				//connexion à la base de données
				try {
					$bdd = new PDO('mysql:host=localhost;dbname=test', 'root', '');
				} catch (Exception $e) {
					exit('Erreur : ' . $e->getMessage());
				}
 
				//Lecture du fichier
				$image = file_get_contents($_FILES['image']['tmp_name']);
 
				$req = $bdd->prepare("INSERT INTO images(nom, description, img, extension) VALUES(:nom, :description, :image, :type)");
				$req->execute(array(
					'nom' => $_POST['nom'],
					'description' => $_POST['description'],
					'image' => $image,
					'type' => $_FILES['image']['type']
					));
 
				echo 'L\'insertion s est bien déroulée !';
			 }
		  }
	  }
  }
?>
 
	<h1>Envoyer une image</h1>
	<form enctype="multipart/form-data" action="traitement.php" method="post">
		<p>
			<label for="nom">Nom : </label><input type="text" name="nom" id="nom" /><br />
			<label for="description">Description : </label><textarea name="description" id="description" rows="10" cols="50"></textarea><br />
			<label for="image">Image : </label><input type="file" name="image" id="image" /><br />
			<label for="validation">Valider : </label><input type="submit" name="validation" id="validation" value="Envoyer" />
		</p>
	</form>
</body>
</html>

Le code est, je pense, assez clair. On vérifie si l’image a été téléchargée. Sinon, on affiche un message d’erreur. Si tout se passe bien, on fait le traitement. On commence par contrôler l’extension du fichier. En fonction de la réponse, message d’erreur ou passage à la suite. Vérification de la taille de l’image : si elle est supérieure à celle définie dans notre constante MAXSIZE, on affiche un message d’erreur. Si par contre elle est conforme, on se connecte, on lit l’image et on enlève les antislash, puis on insère toutes nos données dans notre table. Facile comme tout, vous voyez.

Une galerie : page galerie.php

Stocker des images, c’est bien, mais les afficher, c’est encore mieux. Non ? Voyons comment faire cela grâce à une galerie (niveau graphisme, ce sera très sommaire, à vous de l’agrémenter avec du CSS).

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
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" >
   <head>
       <title>Ma galerie d'images</title>
       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
	   <style type="text/css">
		body {
			width: 95%;
		}
 
		div {
			width: 22%;
			float: left;
			text-align: center;
			border: 1px solid black;
			margin: 5px;
			padding:  5px;
		}
 
		p {
			text-align: left;
		}
 
		a {
			color: #000000;
			text-decoration: none;
		}
	   </style>
   </head>
   <body>
 
	<h1>Ma galerie d'images</h1>
 
	<?php
	    try {
		$bdd = new PDO('mysql:host=localhost;dbname=test', 'root', '');
               } catch (Exception $e) {
		exit('Erreur : ' . $e->getMessage());
	    }
 
	    $reponse = $bdd->query('SELECT id_img, nom, description FROM images');
	    while($result = $reponse->fetch()) {
 
		echo '<div>';
		echo '<a href="apercu.php?id_img='.$result['id_img'].'"><img src="apercu.php?id_img='.$result['id_img'].'" alt="'.$result['nom'].'" title="'.$result['nom'].'" /></a>';
		echo '<p>Description : '.$result["description"].'</p>';
		echo '</div>';
	    }
 
	    $reponse->closeCursor();
	?>
 
</body>
</html>

Je reviens sur un point dans la partie suivante sur cette ligne de code :

1
2
3
<?php
     echo '<a href="apercu.php?id_img='.$result[id_img].'"><img src="apercu.php?id_img='.$result[id_img].'" alt="'.$result[nom].'" title="'.$result[nom].'" /></a>';
?>

Pas de commentaires à faire sur le reste, elle est simple à comprendre.

Au final, vous obtenez le rendu suivant :

Aperçu de la galerie

Aperçu de la galerie

Affichage de l’image : page apercu.php

Souvenez vous de ce code :

1
2
3
<?php
     echo '<a href="apercu.php?id_img='.$result[id_img].'"><img src="apercu.php?id_img='.$result[id_img].'" alt="'.$result[nom].'" title="'.$result[nom].'" /></a>';
?>

Pour afficher une image, il n’y a aucun changement par rapport à ce que vous connaissez à savoir :

1
<img src="monImage.Extension" alt="unNom" title="unNom" /></a>';

Seulement, notre image n’est plus présente physiquement dans notre arborescence, mais dans notre base de données. Il faut donc réaliser un script PHP qui va récupérer notre image à partir de son identifiant.
Voici donc notre page apercu.php sur laquelle nous allons récupérer notre image à partir de l’identifiant.

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
<?php
    //si nous avons une image
    if(!empty($_GET['id_img'])) {
 
	//connexion à la base de données
	try {
		$bdd = new PDO('mysql:host=localhost;dbname=test', 'root', '');
	} catch (Exception $e) {
		exit('Erreur : ' . $e->getMessage());
	}
 
	//on sécurise notre donnée
	$idImg = intval($_GET['id_img']);
 
	//la requète qui récupère l'image à partir de l'identifiant
	$req = $bdd->prepare('SELECT extension, img FROM images WHERE id_img = ?');
	$req->execute(array($idImg));		
 
	if($req->rowCount() != 1)
		echo 'L\'image n\'existe pas !';
	else {
		//on stocke les données dans un tableau
		$donnees = $req->fetch();		
		//on indique qu'on affiche une image
		header ("Content-type: ".$donnees['extension']);
		//on affiche l'image en elle même
		echo $donnees['img'];
	}
 
	$req->closeCursor();
 
    } else
           echo 'Vous n avez pas sélectionné d image !';
?>

Si vous allez sur cette page, vous aurez :

Affichage d'une seule image

Affichage d'une seule image