Discussion:
Image dans un champ BLOB sous MySQL : incompatible ?
(trop ancien pour répondre)
S***@gmail.com
2007-02-12 11:25:01 UTC
Permalink
Bonjour,

Je cherche à stocker une image dans un champ de type BLOB d'une base
de données sous MySQL. Jusque là, rien de bien compliqué :

$fichier=file_get_contents("/images/image.jpg"); // On transforme le
fichier en une chaîne compatible avec BLOB.
$fichier = addslashes ($fichier); // (Pour éviter de déclencher un bug
MySQL)
mysql_query ("INSERT INTO table(id,img) VALUES ('',' ".$fichier."
')");


Maintenant si je veux afficher, je suis obligé de faire tout ça:

header("Content-type: image/jpg"); // Mise en place d'un en-tête MIME
de type jpeg.
$reponse = mysql_query ("SELECT img FROM table WHERE id='1' ");
$donnees = mysql_fetch_array($reponse);
$image = stripslashes($donnees['img']); // On récupère la chaine de
départ dans une variable.
$image = imagecreatefromstring($image); // On convertit la chaine en
une ressource image GD
imagejpeg($image); // On affiche l'image encodée en JPEG.

Sauf que ça marche pas !!!

La fonction "imagecreatefromstring" renvoie l'erreur suivante :
"Warning: imagecreatefromstring() [function.imagecreatefromstring]:
Data is not in a recognized format [...]"

Je me suis donc interrogé sur l'origine du problème, et j'ai testé le
code suivant :

$fichier=file_get_contents("/images/image.jpg"); // Conversion du
fichier en chaine binaire.
$fichier = addslashes ($fichier); // Ajout de slashes devant les
caractères spéciaux.

header("Content-type: image/jpg"); // Mise en place d'un en-tête MIME
de type jpeg.
$image = stripslashes($fichier); // "Nettoyage" des slashes
précédemment ajoutés.
$image = imagecreatefromstring($image); // Conversion de la chaîne
binaire en ressource image GD.
imagejpeg($image); // Affichage de l'image encodée en JPEG.

Or ce code fonctionne parfaitement.

J'en ai donc déduit que la chaîne était modifiée soit lors de son
chargement dans la table, soit lors de la conversion de la ressource
résultat en tableau. Un autre possibilité serait que MySQL renvoie un
résultat différent de ce qui est réellement stocké dans la base.

J'ai vérifié que la chaîne était effectivement différente entre
l'entrée et la sortie en comparant les md5, mais je ne sais pas
comment tester sélectivement les différentes hypothèses proposées ci-
dessus

Je me suis également assuré que la taille des fichiers n'était pas en
cause, mais mes champs sont de type "LONGBLOB", qui limite la taille à
2^32 octets, soit 4 Mio, et j'ai effectué mes tests avec une image de
35,8 Kio.

Je ne comprend donc pas l'origine du problème. Quelqu'un aurait-il une
idée ?

Merci beaucoup !
Laurent Duretz
2007-02-12 13:45:11 UTC
Permalink
L'utilisation de mysql_real_escape_string() est préférable à
addslashes() pour les données binaires

addslashes ne protège pas tous les caractères "sensibles" pour mysql
comme le fait mysql_real_escape_string.
P'tit Marcel
2007-02-12 23:51:48 UTC
Permalink
Post by Laurent Duretz
L'utilisation de mysql_real_escape_string() est préférable à
addslashes() pour les données binaires
Si cela ne suffit pas pour éviter la corruption des données, alors on
peut imaginer de stocker l'information de façon encodée :


$fichier = file_get_contents("/images/image.jpg");
$fichier = base64_encode($fichier);
$res= mysql_query ("INSERT INTO ... VALUES ('$fichier')");

et à l'arrivée, tu utilise base64_decode pour restituer l'information
d'origine.


sans garantie de bon fonctionnement ou de pertinence.
--
P'tit Marcel
John GALLET
2007-02-13 12:17:50 UTC
Permalink
Quelqu'un aurait-il une idée ?
Stocker le chemin du fichier dans un varchar(100) au lieu de s'emmerder
avec du binaire est également possible dans 99,99% des cas.
S***@gmail.com
2007-02-13 20:45:18 UTC
Permalink
Post by John GALLET
Quelqu'un aurait-il une idée ?
Stocker le chemin du fichier dans un varchar(100) au lieu de s'emmerder
avec du binaire est également possible dans 99,99% des cas.
Ce serait effectivement faisable, mais alourdirait considérablement le
code vu l'utilisation que j'en fait.

J'avais répondu, mais apparemment ma réponse s'est perdue en route...

A force d'approfondir mes tests, j'ai fini par regarder la longueur de
la chaîne à différents moments, avec les résultats suivant :
- au départ : environ 35000 caractères dans mon cas
- après addslashes ou mysql_real_escape_string = environ 500 de plus
- après mysql_query(SELECT INTO ... ) et mysql_fetch_array : 2 de plus
qu'au départ
- après stripslashes : 200 de moins qu'au départ !!!

Du coup j'ai fait un trim() après la récupération de la chaîne dans la
base et j'ai viré le strislashes, et ça marche.

Du coup je me demande si ce petit 'détail' est un problème connu, un
bug, un fonctionnement normal..? En tout cas ce serait bien si ça
pouvait indiqué quelque part parce que j'y ai perdu plein de temps
bêtement.

Merci pour vos réponses, qui n'auront pas servi a résoudre le
problème, mais m'auront au moins permis d'apprendre des trucs.
eric
2007-02-24 10:05:12 UTC
Permalink
Post by John GALLET
Quelqu'un aurait-il une idée ?
Stocker le chemin du fichier dans un varchar(100) au lieu de s'emmerder
avec du binaire est également possible dans 99,99% des cas.
Je rajouterais qu'il y a aucune utilité de stocker des infos binaires
dans une base de donnée, de plus ça dimininue les performance.

Le système de fichiers est fais pour ça, autant l'utiliser.

Continuer la lecture sur narkive:
Loading...