IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PHP & Base de données Discussion :

INSERT et SELECT d'un BLOB avec PHP et MS Access


Sujet :

PHP & Base de données

  1. #1
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Décembre 2009
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 42
    Points : 17
    Points
    17
    Par défaut INSERT et SELECT d'un BLOB avec PHP et MS Access
    J'ai déjà fait ça en ASP avec Oracle, en PHP avec MySQL.
    Avec Access, ça coince.
    Le code suivant est plus simple qu'il n'y paraît mais il s'est allongé du fait des multiples affichages et précautions de débogage.
    La variable $realData à false permet de travailler avec la petite chaîne "ABCD" plutôt que le contenu du fichier BMP.
    Les écritures dans les fichier logo2 et logo3 permettent de vérifier ce qui est inséré ou lu dans la base de données avec l'éditeur de texte.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    <?
    ob_start();
    ### GLOBAL ####################################################################
    function OuiNon ( $condition ) {
      # Retourne OUI, NON, NULL ou $condition
    	if      ($condition===true)  return 'OUI';
    	else if ($condition===false) return 'NON';
    	else if ($condition===null)  return 'NULL';
    	else                         return $condition;
    }
    function hex2bin ( $data ) {
    	$len = strlen( $data );
    	return pack( 'H'.$len, $data );
    }
    $DSNless = 'Driver={Microsoft Access Driver (*.mdb)};Dbq=';
    define( '¶', "\n" );
    ini_set('error_prepend_string','');
    ini_set('error_append_string','');
    ini_set('html_errors','Off');
    $realData = true; // For debug, I don't use real data from the file
    ob_end_clean();
    ###############################################################################
    ### PAGE Début ################################################################
    ###############################################################################
     
    header('Content-Type: text/plain; charset=ASCII');
    $cnx = odbc_connect( $DSNless.'test.mdb', '','' ); // , SQL_CUR_USE_IF_NEEDED
     
    ### INSERT ####################################################################
    	if ( $realData ) {
    		$data = file_get_contents( 'logo.bmp' );
    		$data = addslashes( $data ); // to avoid a ' to accidentally close a string
    	} else {
    		$data = chr(65).chr(66).chr(67).chr(68); // = "ABCD" sure ! Even from UTF-8 PHP file.
    	}
    	echo "file_put_contents: ".OuiNon( file_put_contents( 'logo2.bmp', $data )).¶;
    	echo "data: ".$data.¶;
    	$SQL = "INSERT INTO `img` ( bin_data ) VALUES ('$data');"; // LONGBINARY côté PHP et Objet OLE côté Access
    	odbc_exec( $cnx, $SQL );
     
    ### SELECT ####################################################################
    	$qry = odbc_exec($cnx, "SELECT * FROM `img` ORDER BY id DESC");// To get the just last inserted, or WHERE id=".$id);
    	if ( odbc_fetch_row( $qry ) ) {
    		//header('Content-type: image/bmp');
    		// ODBC_BINMODE_PASSTHRU ODBC_BINMODE_RETURN ODBC_BINMODE_CONVERT
    		echo "odbc_binmode: ".OuiNon(  odbc_binmode( $qry, ODBC_BINMODE_RETURN )).¶;
    		$id   = odbc_result( $qry, 'id' );
    		$data = odbc_result( $qry, 'bin_data' );
    		echo ¶;
    		echo "id: ".$id.¶;
    		echo "file_put_contents: ".OuiNon(  file_put_contents( 'logo3.bmp', $data )).¶;
    		echo "mb_detect_encoding: ".OuiNon(  mb_detect_encoding ( $data, 'ASCII', true )).¶;
    		echo "mb_check_encoding ASCII: ".OuiNon(  mb_check_encoding( $data, 'ASCII' )).¶;
    		echo "data: ".$data.¶;
    		//mb_convert_encoding( $data, '8bit', 'ASCII' );
    		//$out = hex2bin($data);
    		//echo "out: ".$out.¶;
    	}
    	else {
    		header('Content-Type: text/plain; charset=ascii');
    		return 'error';
    	}
     
    odbc_close($cnx);
    ###############################################################################
    ### PAGE Fin ##################################################################
    ###############################################################################
    ?>
    Quand je veux stocker "ABCD", je récupère toujours "A�B�C�D�".
    Et les solutions que j'ai pu trouver dans les forums ne résolvent pas le problème, même quand elles indiquent que celui-ci est résolu.
    Quelqu'un aurait-il une solution ? une piste ?
    Merci pour votre aide.

  2. #2
    Membre émérite
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Points : 2 446
    Points
    2 446
    Par défaut
    Le réflexe serait de vérifier l'encodage des éléments d'encodage de la chaine de sauvegarde.

    si tu as des 0 hexadécimaux entre toutes tes lettres, ça ressemble à un problème que j'ai déjà eu... str_replace( chr(0),'',$chaine) serait un moyen efficace de contourner le problème...
    PHP fait nativement la validation d'adresse électronique .
    Celui qui a inventé mysql_connect(...) or die() est déjà mort plusieurs fois.

    Utilisez le bouton résolu!

  3. #3
    Membre émérite
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Points : 2 446
    Points
    2 446
    Par défaut
    enfait je me demande vraiment pourquoi tu prends toutes ses précautions pour encoder la chaine... alors qu'on peut faire des vrais trucs pour la sécurité.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $a = 1;
    $b = 2;
    $c = 3;
    $stmt    = odbc_prepare($conn, 'CALL myproc(?,?,?)');
    $success = odbc_execute($stmt, array($a, $b, $c));
    PHP fait nativement la validation d'adresse électronique .
    Celui qui a inventé mysql_connect(...) or die() est déjà mort plusieurs fois.

    Utilisez le bouton résolu!

  4. #4
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Décembre 2009
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 42
    Points : 17
    Points
    17
    Par défaut
    Tout d'abord, merci pour cette réponse si rapide.

    J'ai ajouté ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    		$out = str_replace( chr(0),'',$data);
    		echo "out: ".$out.¶;
    C'est très bien, les caractères NULL sont supprimés.
    Mais :

    1) Après avoir pris la peine d'utiliser un champs de type LONGBINARY et d'avoir utilisé la fonction odbc_binmode de PHP, je suis un peu ennuyé d'avoir à utiliser un replace.

    2) Dans ma sortie, je retrouve tous les caractères d'échappement. Est-ce que leur fonction n'est pas simplement de passer la barrière syntaxique d'SQL, mais sans s'enregistrer réellement dans la base ? Je n'ai pas vérifié mais il me semble que lorsque je fais ça sur un champs texte, je ne retrouve pas les "\" dans la base.

    3) Enfin, j'ai essayer déjà le odbc_prepare mais sans succès. Il n'y a pas de procédures stockées avec Access 2000 (*.mdb) même si c'est Access 2010 que j'utilise.

    4) J'ai lu dans le Manuel de PHP :
    Les types ODBC SQL affectés sont BINARY, VARBINARY et LONGVARBINARY.
    Et non LONGBINARY. Est-ce donc que l'utilisation de la fonction odbc_binmode n'est pas totalement inutile ici ?

    5) Le Manuel dit aussi ceci :
    Lorsqu'une donnée SQL est convertie en caractère C, les 8 bits du caractère source sont représentés par deux caractères ASCII. Ces caractères sont des représentations ASCII des nombres au format hexadécimal. Par exemple, le binaire 00000001 est converti en "01" et le binaire 11111111 est converti en "FF".
    Mais l'utilisation de la fonction hex2bin présentée je ne sais plus où comme LA solution, me dit qu'il ne s'agit pas de valeurs hexadécimales valides.

    Je reste donc toujours coincé.

  5. #5
    Membre émérite
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Points : 2 446
    Points
    2 446
    Par défaut
    j'ai pas l'esprit en face des yeux aujourd'hui je seche sur toutes les questions.

    Dans ma sortie, je retrouve tous les caractères d'échappement. Est-ce que leur fonction n'est pas simplement de passer la barrière syntaxique d'SQL, mais sans s'enregistrer réellement dans la base ? Je n'ai pas vérifié mais il me semble que lorsque je fais ça sur un champs texte, je ne retrouve pas les "\" dans la base.
    il y a des caractères d'échappements qui sont "absorbés" pas l'analyseur lexical de PHP... ça dépend de leurs nombre. Et les caractères d'échappement avec Odbc et Access, de mémoire c'est une plaie.

    Quoi dire pour t'aider...

    Pourquoi un binary et pas du texte ? c'est bien du texte le contenu que tu stockes?
    PHP fait nativement la validation d'adresse électronique .
    Celui qui a inventé mysql_connect(...) or die() est déjà mort plusieurs fois.

    Utilisez le bouton résolu!

  6. #6
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Décembre 2009
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 42
    Points : 17
    Points
    17
    Par défaut
    Bah... non, quand-même !
    On peut aussi stocker les dates dans des champs texte si on veut.
    Tout est du texte si on veut.
    Et bien sûr, tout est du binaire aussi.
    Je voudrais quand même faire le truc proprement. Je l'ai déjà fait en plus.

    La remarque sur la gestion par PHP des caractères d'échappement:
    ... ça dépend de leurs nombre
    m’effraie un peu...

  7. #7
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Décembre 2009
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 42
    Points : 17
    Points
    17
    Par défaut
    L'ajout d'un :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    		$out = stripcslashes ( $out );
    ne change rien à l'affaire...

  8. #8
    Membre émérite
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Points : 2 446
    Points
    2 446
    Par défaut
    bah non.

    sur un systeme windows pour avoir deux \\ dans une variable il en faut 4
    '\\\\' ... banalité... j'arrive pas à voir le problème.
    PHP fait nativement la validation d'adresse électronique .
    Celui qui a inventé mysql_connect(...) or die() est déjà mort plusieurs fois.

    Utilisez le bouton résolu!

  9. #9
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Décembre 2009
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 42
    Points : 17
    Points
    17
    Par défaut
    On s'écarte du problème.
    Oui il en faut 4. Mais la fonction addslashes est faite pour ça. Le PHP qui tourne sait très bien qu'il est sous Windows, il a été compilé pour cela.

    Le vrai problème c'est qu'il ne faudrait utiliser ni addslashes ni replace.

    Si quelqu'un, comme certains le disent dans des forum, a vraiment la solution, qu'il le dise. C'est l'honneur de PHP qui est en jeu !

    Ou bien c'est moi qui suis une grosse burnasse en informatique et qui n'ai rien compris à l'utilisation des données binaires ?
    (Note: n'en profitez pas, je suis le seul à pouvoir m'insulter, hum?)

Discussions similaires

  1. [MySQL] insertion d'info dans une base avec php pdo
    Par hémilie dans le forum PHP & Base de données
    Réponses: 10
    Dernier message: 13/02/2015, 11h34
  2. [MySQL] Affichage d'image blob avec PHP
    Par minichips dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 17/03/2014, 16h44
  3. Lire et afficher des BLOB avec PHP
    Par CFGilles dans le forum SQL
    Réponses: 4
    Dernier message: 04/08/2008, 15h19
  4. [SQL] Récupérer un BLOB avec php
    Par identifiant_bidon dans le forum PHP & Base de données
    Réponses: 8
    Dernier message: 06/11/2007, 12h24
  5. insertion des blob avec LOAD DATA...
    Par orli1x51 dans le forum SQL Procédural
    Réponses: 2
    Dernier message: 27/10/2003, 18h05

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo