Précédent   Forum des professionnels en informatique > PHP > PHP & SGBD > PHP & PostgreSQL
PHP & PostgreSQL Forum d'entraide sur PostgreSQL avec PHP. Avant de poster -> FAQ PostgreSQL, Cours PostgreSQL. Pour les questions concernant le moteur PostgreSQL plutôt que les fonctions PHP, merci d'utiliser le forum PostgreSQL.
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 15/02/2011, 10h28   #1
Membre du Club
 
Inscription : janvier 2008
Messages : 121
Détails du profil
Informations forums :
Inscription : janvier 2008
Messages : 121
Points : 46
Points : 46
Par défaut Afficher une image stockée dans la base avec PHP / PDO / PostgresSQL

Bonjour,

Je suis débutant en PHP et j'ai une table d'articles avec une colonne contenant une image (type OID).

J'aimerais afficher qlq données de l'article et l'image mais après plusieures tentatives en suivant la doc PHP PDO (presque inexistante) et après des heures de recherches et de tests... je n'y arrive pas. Au mieux j'ai une image vide. Pourtant je recepère bien l'OID. C'est la lecture du LargeObject qui pose problème.

Par ailleurs, je travaille sur une application Java qui se connecte à la même bdd. Les données correctes et les images parfaitement lisibles.

Voici mon index.php
Code :
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
<?php
$PARAM_hote         ='localhost';   // le chemin vers le serveur
$PARAM_port         ='5432';        // le port de connexion
$PARAM_nom_bd       ='test_db';     // le nom de votre base de données
$PARAM_utilisateur  ='root';       // nom d'utilisateur pour se connecter
$PARAM_mot_passe    =''; // mot de passe de l'utilisateur pour se connecter
?>
 
<!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" lang="fr">
   <head>
       <title>Test</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
   </head>
 
   <body>
 
       <?php include("entete.php"); ?>
 
       <?php include("menus.php"); ?>
 
       <!-- Le corps -->
 
       <div id="corps">
           <h1>Liste des articles qui ont une photo</h1>
 
        <pre>
 
        <?php
        try
        {
            $pdo_options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;
            $connexion = new PDO('pgsql:host='.$PARAM_hote.';port='.$PARAM_port.';dbname='.$PARAM_nom_bd, $PARAM_utilisateur, $PARAM_mot_passe);
 
            echo 'Utilisateur ' . $PARAM_utilisateur . ' connecté';
 
            // On récupère les articles qui ont une photo
            $resultats = $connexion->prepare(
                    'SELECT articles.art_id, nom_article, quant_stock, prix_vente, photo_data_mini
                     FROM articles
                     LEFT OUTER JOIN noms_article ON articles.art_id = noms_article.art_id
                     WHERE articles.photo_taille > 0');
 
            $resultats->execute(array());
            $resultats->setFetchMode(PDO::FETCH_OBJ); // on dit qu'on veut que le résultat soit récupérable sous forme d'objet
 
            echo '<ul>';
            while ($donnees = $resultats->fetch())
            {
                echo '<li>' . $donnees->art_id . ' - ' . $donnees->nom_article . ' ' . $donnees->photo_data_mini . '<img src=affiche_image.php?art_id=' . $donnees->art_id . '> ' . '</li>';
            }
            echo '</ul>';
 
            $resultats->closeCursor(); // Termine le traitement de la requête
 
 
        }
        catch (Exception $e)
        {
                die('Erreur : ' . $e->getMessage());
        }
        ?>
 
        </pre>
 
       </div>
 
       <?php include("pied_de_page.php"); ?>
 
   </body>
</html>
et affiche_image, 1ère version
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
// configuration
$PARAM_hote         ='localhost';   // le chemin vers le serveur
$PARAM_port         ='5432';        // le port de connexion
$PARAM_nom_bd       ='test_db';     // le nom de votre base de données
$PARAM_utilisateur  ='root';       // nom d'utilisateur pour se connecter
$PARAM_mot_passe    =''; // mot de passe de l'utilisateur pour se connecter
 
// database connection
$conn = new PDO('pgsql:host='.$PARAM_hote.';port='.$PARAM_port.';dbname='.$PARAM_nom_bd, $PARAM_utilisateur, $PARAM_mot_passe);
 
// query
$sql = "SELECT photo_data_mini FROM articles WHERE art_id=".$_GET['id'];
 
$q = $conn->prepare($sql);
$q->execute();
 
$q->bindColumn(1, $lob, PDO::PARAM_LOB);
$q->fetch(PDO::FETCH_BOUND);
 
header("Content-Type: image/jpeg");
echo $lob;
?>
et affiche_image, 2ème version
Code :
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
<?php
// configuration
$PARAM_hote         ='localhost';   // le chemin vers le serveur
$PARAM_port         ='5432';        // le port de connexion
$PARAM_nom_bd       ='test_db';     // le nom de votre base de données
$PARAM_utilisateur  ='root';       // nom d'utilisateur pour se connecter
$PARAM_mot_passe    =''; // mot de passe de l'utilisateur pour se connecter
 
// connection à la base
$db = new PDO('pgsql:host='.$PARAM_hote.';port='.$PARAM_port.';dbname='.$PARAM_nom_bd, $PARAM_utilisateur, $PARAM_mot_passe);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
 
// requete
$stmt = $db->prepare("SELECT photo_data_mini FROM articles WHERE art_id = ?");
$stmt->execute(array($_GET['art_id']));
 
$stmt->bindColumn('photo_data_mini', $lob, PDO::PARAM_LOB);
$stmt->fetch(PDO::FETCH_BOUND);
 
//echo $lob;
 
$stream = $db->pgsqlLOBOpen($lob, 'r');
$data = stream_get_contents($stream);
 
header("Content-type: image/jpeg");
echo $data;
 
// ou
//fpassthru($stream);
// ou
//echo stream_get_contents($stream);
 
?>
Il y a des milliers d'artiles organisé en familles (et plus dans un avenir proche) dans la bdd et dans le but d'améliorer les performances, j'aimerais me passer de affiche_image.php et tout faire dans la boucle principale de index.php. Possible ?

Merci d'avance.
genamiga est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2011, 11h38   #2
Modérateur
 
Avatar de sabotage
 
Homme Vincent
Inscription : juillet 2005
Messages : 14 929
Détails du profil
Informations personnelles :
Nom : Homme Vincent

Informations forums :
Inscription : juillet 2005
Messages : 14 929
Points : 16 381
Points : 16 381
Dans la doc "presque inexistante" je lis ça au sujet de bindcolumn :
Citation:
Cependant, pour pouvoir lier une colonne de type LOB avec un flux lors de l'utilisation du pilote PostGreSQL, les applications doivent appeler cette méthode avant d'appeler PDOStatement::execute(), sous peine de recevoir l'objet OID sous forme d'entier.
sabotage est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2011, 14h47   #3
Membre du Club
 
Inscription : janvier 2008
Messages : 121
Détails du profil
Informations forums :
Inscription : janvier 2008
Messages : 121
Points : 46
Points : 46
En effet dans la doc bindColumn il parle du cas particulier de PostgreSQL ou il faut faire le contraire...

Donc en effet si je fais mon bindColumn après l'execute j'ai l'OID.

Mais si le fais avant cela ne fonctionne pas vraiment mieux...

En utilisant affiche_image, 2ème version

si je fais
j'obtiens
Je suppose que cela représente le flux ?

Mais comment je fais pour avoir l'image ?

PS : Dans la doc PHP de la méthode pgsqlLOBOpen, l'exemple donné ne fais même pas appel à la méthode...
genamiga est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2011, 16h27   #4
Modérateur
 
Inscription : septembre 2010
Messages : 7 101
Détails du profil
Informations forums :
Inscription : septembre 2010
Messages : 7 101
Points : 8 466
Points : 8 466
fais un :
Code :
var_dump(get_resource_type($lob));
__________________
http://blog.stealth35.com/
stealth35 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2011, 16h39   #5
Membre du Club
 
Inscription : janvier 2008
Messages : 121
Détails du profil
Informations forums :
Inscription : janvier 2008
Messages : 121
Points : 46
Points : 46
avant
Code :
$stream = $pdo->pgsqlLOBOpen($lob, 'r');
ça me donne : (l'OID certainement)

et si je le mets après, le résultat = rien du tout

juste après pgsqlLOBOpen, var_dump(get_resource_type($stream)); ne donne rien non plus...
genamiga est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2011, 16h40   #6
Modérateur
 
Inscription : septembre 2010
Messages : 7 101
Détails du profil
Informations forums :
Inscription : septembre 2010
Messages : 7 101
Points : 8 466
Points : 8 466
oki donc c'est
Code :
echo stream_get_contents($stream);
__________________
http://blog.stealth35.com/
stealth35 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2011, 16h59   #7
Membre du Club
 
Inscription : janvier 2008
Messages : 121
Détails du profil
Informations forums :
Inscription : janvier 2008
Messages : 121
Points : 46
Points : 46
résultat = rien du tout
genamiga est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2011, 17h04   #8
Modérateur
 
Inscription : septembre 2010
Messages : 7 101
Détails du profil
Informations forums :
Inscription : septembre 2010
Messages : 7 101
Points : 8 466
Points : 8 466
Citation:
Envoyé par genamiga Voir le message
résultat = rien du tout
fais un var_dump alors,
montre tout ton dernier code
__________________
http://blog.stealth35.com/
stealth35 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2011, 17h13   #9
Membre du Club
 
Inscription : janvier 2008
Messages : 121
Détails du profil
Informations forums :
Inscription : janvier 2008
Messages : 121
Points : 46
Points : 46
Code :
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
<?php
// configuration
$PARAM_hote         ='localhost';   // le chemin vers le serveur
$PARAM_port         ='5432';        // le port de connexion
$PARAM_nom_bd       ='test_db';     // le nom de votre base de données
$PARAM_utilisateur  ='root';       // nom d'utilisateur pour se connecter
$PARAM_mot_passe    =''; // mot de passe de l'utilisateur pour se connecter
 
// connection à la base
$db = new PDO('pgsql:host='.$PARAM_hote.';port='.$PARAM_port.';dbname='.$PARAM_nom_bd, $PARAM_utilisateur, $PARAM_mot_passe);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
 
// requete
$stmt = $db->prepare("SELECT photo_data_mini FROM articles WHERE art_id = ?");
$stmt->bindColumn('photo_data_mini', $lob, PDO::PARAM_LOB);
$stmt->execute(array($_GET['art_id']));
$stmt->fetch(PDO::FETCH_BOUND);
 
//var_dump(get_resource_type($lob)); // résultat --> string(6) "stream" --> echo $lob donne : Resource id #2
 
$stream = $db->pgsqlLOBOpen($lob, 'r');
 
//var_dump(get_resource_type($lob)); // résultat --> rien
//var_dump(get_resource_type($stream)); // résultat --> rien
 
$data = stream_get_contents($stream);
 
//var_dump(get_resource_type($data)); // résultat --> rien
 
header("Content-type: image/jpeg");
echo $data;
 
// ou
//fpassthru($stream);
// ou
//echo stream_get_contents($stream);
?>
genamiga est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2011, 17h25   #10
Modérateur
 
Inscription : septembre 2010
Messages : 7 101
Détails du profil
Informations forums :
Inscription : septembre 2010
Messages : 7 101
Points : 8 466
Points : 8 466
enlève tes headers quand tu fais des tests
__________________
http://blog.stealth35.com/
stealth35 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2011, 17h36   #11
Membre du Club
 
Inscription : janvier 2008
Messages : 121
Détails du profil
Informations forums :
Inscription : janvier 2008
Messages : 121
Points : 46
Points : 46
ça change rien
genamiga est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2011, 17h38   #12
Modérateur
 
Inscription : septembre 2010
Messages : 7 101
Détails du profil
Informations forums :
Inscription : septembre 2010
Messages : 7 101
Points : 8 466
Points : 8 466
Citation:
Envoyé par genamiga Voir le message
ça change rien
si tu va pouvoir mieux débugger, en faisant par exemple :
__________________
http://blog.stealth35.com/
stealth35 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2011, 17h50   #13
Membre du Club
 
Inscription : janvier 2008
Messages : 121
Détails du profil
Informations forums :
Inscription : janvier 2008
Messages : 121
Points : 46
Points : 46
Code php :
1
2
3
4
5
var_dump($lob); // résultat --> resource(2) of type (stream) 
 
var_dump($stream); // résultat --> rien
 
var_dump($data); // résultat --> rien
genamiga est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2011, 17h55   #14
Modérateur
 
Inscription : septembre 2010
Messages : 7 101
Détails du profil
Informations forums :
Inscription : septembre 2010
Messages : 7 101
Points : 8 466
Points : 8 466
Citation:
Envoyé par genamiga Voir le message
var_dump($lob); // résultat --> resource(2) of type (stream)

var_dump($stream); // résultat --> rien

var_dump($data); // résultat --> rien
il a pas l'air de le récupérer au pire, fait le en string standard
sinon que donne un
Code :
var_dump(stream_get_meta_data($lob));
__________________
http://blog.stealth35.com/
stealth35 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2011, 17h57   #15
Membre du Club
 
Inscription : janvier 2008
Messages : 121
Détails du profil
Informations forums :
Inscription : janvier 2008
Messages : 121
Points : 46
Points : 46
array(7) { ["stream_type"]=> string(20) "pdo_pgsql lob stream" ["mode"]=> string(3) "r+b" ["unread_bytes"]=> int(0) ["seekable"]=> bool(true) ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) }

Extrait du log Apache

Code :
1
2
[Tue Feb 15 18:06:15 2011] [error] [client 127.0.0.1] PHP Warning:  PDO::pgsqlLOBOpen() expects parameter 1 to be string, resource given in D:\\Developpement\\WebDev\\ApachePhp\\apache\\www\\PhpProject1\\affiche_image_1.php on line 23
[Tue Feb 15 18:06:15 2011] [error] [client 127.0.0.1] PHP Warning:  stream_get_contents() expects parameter 1 to be resource, boolean given in D:\\Developpement\\WebDev\\ApachePhp\\apache\\www\\PhpProject1\\affiche_image_1.php on line 29
la ligne 23
Code :
$stream = $db->pgsqlLOBOpen($lob, 'r');
la ligne 29
Code :
$data = stream_get_contents($stream);
genamiga est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2011, 18h13   #16
Modérateur
 
Inscription : septembre 2010
Messages : 7 101
Détails du profil
Informations forums :
Inscription : septembre 2010
Messages : 7 101
Points : 8 466
Points : 8 466
visiblement il est vide
__________________
http://blog.stealth35.com/
stealth35 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2011, 18h54   #17
Membre du Club
 
Inscription : janvier 2008
Messages : 121
Détails du profil
Informations forums :
Inscription : janvier 2008
Messages : 121
Points : 46
Points : 46
je suis sûr à 100% que cette colonne contient une image.
genamiga est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/02/2011, 10h08   #18
Modérateur
 
Inscription : septembre 2010
Messages : 7 101
Détails du profil
Informations forums :
Inscription : septembre 2010
Messages : 7 101
Points : 8 466
Points : 8 466
Citation:
Envoyé par genamiga Voir le message
je suis sûr à 100% que cette colonne contient une image.
essaye avec une ou t'es vraiment sur
__________________
http://blog.stealth35.com/
stealth35 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/02/2011, 13h02   #19
Membre du Club
 
Inscription : janvier 2008
Messages : 121
Détails du profil
Informations forums :
Inscription : janvier 2008
Messages : 121
Points : 46
Points : 46
En PHP je suis super nul...je débute...ça se voit...mais en SQL c'est autre chose et je sais ce qu'il y a dans ma bdd

Mais j'ai de bonnes nouvelles...j'ai trouvé.

Quand je critiquais la doc...

Voici le code qui fonctionne :
Code :
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
<?php
// configuration
$PARAM_hote         ='localhost';   // le chemin vers le serveur
$PARAM_port         ='5432';        // le port de connexion
$PARAM_nom_bd       ='test_db';     // le nom de votre base de données
$PARAM_utilisateur  ='root';       // nom d'utilisateur pour se connecter
$PARAM_mot_passe    =''; // mot de passe de l'utilisateur pour se connecter
 
// connection à la base
$db = new PDO('pgsql:host='.$PARAM_hote.';port='.$PARAM_port.';dbname='.$PARAM_nom_bd, $PARAM_utilisateur, $PARAM_mot_passe);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->beginTransaction();
 
// requete
$stmt = $db->prepare("SELECT photo_nom, photo_taille, photo_data, photo_data_mini FROM articles WHERE art_id = ?");
$stmt->execute(array($_GET['art_id']));
$stmt->bindColumn('photo_nom', $photo_nom);
$stmt->bindColumn('photo_taille', $photo_taille);
$stmt->bindColumn('photo_data_mini', $lob, PDO::PARAM_LOB);
$stmt->fetch(PDO::FETCH_BOUND);
 
//echo 'photo_nom = ' . $photo_nom . ' <BR> photo_taille = ' . $photo_taille . ' <BR> $lob = ' . $lob . '<BR><BR>';
 
echo stream_get_contents($db->pgsqlLOBOpen($lob, 'r'));
?>
Pour résumé, comme la rappelais sabotage, la doc de bindColumn dit que dans le cas de l'utilisation du pilote PostGreSQL, il faut appeler cette methode AVANT d'appeler PDOStatement::execute()...mais ici pour que cela fonctionne correctement, j'ai appelé la méthode APRES... comme dans l'exemple donné dans la doc de pgsqlLOBOpen (qui ne fait pas d'appel à la méthode)

En fait dans mon code du début j'avais simplement oublier le
Code :
$db->beginTransaction();
genamiga est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 10h51.


 
 
 
 
Partenaires

Hébergement Web