Kai: Bild aus Datenbank ausgeben

Hallöchen,

habe in meiner Datenbank Bilder hinterlegt. Die möchte ich nun in eine Website einbinden und ausgeben lassen. Mit dem Speichern in der Datebank hat geklappt, aber das ausgeben funktioniert nicht. Ich bekomme nur:

Object id #1, wenn ich einfach echo $bild mache.

Füge ich der Datei Content-Type: image/jpeg hinzu, dann bekomm ich die Ausgabe des Pfads der Datei (also der PHP-Datei).

Was mache ich falsche?

Grüße
Kai

  1. Hello,

    Was mache ich falsche?

    erstaunlich, was manche Leute glauben, wie gut unsere Glaskugeln leisten können. Die Informationen deinerseits sind doch ein Wenig spärlich. Vielleicht hilft dir dieser Artikel weiter...

    MfG
    Rouven

    --
    -------------------
    Death is nature's way of telling you to slow down.
    1. echo $begrüßung;

      Vielleicht hilft dir dieser Artikel weiter...

      Man sollte aber mindestens hinzufügen, dass das dort zu sehende addslashes() zugunsten eines mysql_real_escape_string() ausgetauscht werden sollte. Außerdem empfiehlt es sich dies auf alle per SQL zu übergebenden Daten anzuwenden, nicht nur auf die Datei-Daten. (Möglicherweise müssen vorher noch Magic Quotes entsorgt werden.)

      $inhalt = fread(fopen(...)) ist auch nicht grade die feine englische Art, werden dabei doch möglicherweise auftretende Fehler völlig ignoriert. Außerdem gibt es heutzutage file_get_contents().

      echo "$verabschiedung $name";

      1. Sorry, Informationen sind wohl wirklich etwas dürftig.

        Also ich habe mich in der Tag an oben genannten Link gehalten und bin danach vorgegangen. Ich greife aber auf eine Oracle XE Datenbank zu, nicht auf eine MySQL-Datenbank. Wie geschrieben, klappt das Speichern auch. Also 100%ig kann ich es nicht sagen, da ich die Ausgabe ja nicht hinbekomme, aber es werden Binärdaten in der DB abgelegt.

        <?php

        require("./login.php");

        if ($con = oci_connect($user, $password, $database)){

        $sql = "begin p_abfrage.bild_bild(:bild_id, :bild);end;";

        $curs = oci_new_cursor($con);
           $result = oci_parse($con, $sql);
           $ID = 1;
           oci_bind_by_name ($result, "bild_id", $ID);
           oci_bind_by_name($result, "bild", $curs, -1, OCI_B_CURSOR);

        oci_execute($result);
           oci_execute($curs);

        $bild = oci_fetch_row($curs);

        $err=OCIError($result);

        if($err==TRUE){ echo " <font size=2>Oracle-Fehler: $err[message]</font><br> ";}

        echo $bild[3]; // da ist das bild abgelegt

        }else{
         echo ' Verbindung fehlgeschlagen!';
           }

        ;
        ?>

        Habe die ID im Skript angegeben um sicherzugehen das was drin steht, hat aber mit Übergabe auch funktioniert (nur das Bild gibt er genausowenig aus). Wenn ich nun "Header( "Content-type: image/jpeg"); " hinzufüge, dann bekomme ich beim Aufruf der Datei den Pfad der Datei. Lasse ich es weg, wird "Object id #1" ausgegeben.

        Grüße Kai!

        1. Hello,

          <?php

          require("./login.php");

          if ($con = oci_connect($user, $password, $database)){

          $sql = "begin p_abfrage.bild_bild(:bild_id, :bild);end;";

          $curs = oci_new_cursor($con);
             $result = oci_parse($con, $sql);
             $ID = 1;
             oci_bind_by_name ($result, "bild_id", $ID);

          woher komt $ID ?

          oci_bind_by_name($result, "bild", $curs, -1, OCI_B_CURSOR);

          oci_execute($result);
             oci_execute($curs);

          $bild = oci_fetch_row($curs);

          $err=OCIError($result);

          if($err==TRUE){ echo " <font size=2>Oracle-Fehler: $err[message]</font><br> ";}

          Das ist witzlos, da der Browser keine Texte darstellt, wenn er einen Bild-Request durchgeführt hat.

          Sag dem Browser vorher, dass ein Bild kommt:, also z.B. ein JPG

          header('Content-type: image/jpeg');

          echo $bild[3]; // da ist das bild abgelegt

          hiernach dürfen keine Daten mehr kommen!

          }else{
          echo ' Verbindung fehlgeschlagen!';
             }

          ;
          ?>

          Harzliche Grüße vom Berg
          http://www.annerschbarrich.de

          Tom

          --
          Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
          Nur selber lernen macht schlau

          1. hi,

            $ID = 1;
               oci_bind_by_name ($result, "bild_id", $ID);

            woher komt $ID ?

            Aus der Zeile darüber - wie er zuvor auch schon beschrieb.

            gruß,
            wahsaga

            --
            /voodoo.css:
            #GeorgeWBush { position:absolute; bottom:-6ft; }
            1. Hello,

              woher komt $ID ?

              Aus der Zeile darüber - wie er zuvor auch schon beschrieb.

              Ach. Manchmal nützt es tatsächlich, genauer zu lesen ;-)

              Hab keine Übung mehr mit dem Forum. Sollte ich mal auffrischen.

              Harzliche Grüße vom Berg
              http://www.annerschbarrich.de

              Tom

              --
              Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
              Nur selber lernen macht schlau

              1. hi Tom,

                War lang schon nicht hier ...

                Stimmt auffallend - wo hast du dich rumgetrieben? :-)

                gruß,
                wahsaga

                --
                /voodoo.css:
                #GeorgeWBush { position:absolute; bottom:-6ft; }
          2. Hallo,

            danke für die Hilfe. Nur leider funktioniert es noch immer nicht. Habe das Content-Type... hinzugefügt und unten drunter auch den else-zweig entfernt und vor das Content-Type gesetzt. Aber die Ausgabe ist "http://localhost/bild.php". Bild ist ein jpg als CLOB in der DB abgelegt. Sonst noch eine Idee woran es liegen könnte?

            Grüße Kai!

            1. Hello,

              danke für die Hilfe. Nur leider funktioniert es noch immer nicht. Habe das Content-Type... hinzugefügt und unten drunter auch den else-zweig entfernt und vor das Content-Type gesetzt. Aber die Ausgabe ist "http://localhost/bild.php". Bild ist ein jpg als CLOB in der DB abgelegt. Sonst noch eine Idee woran es liegen könnte?

              Der Else-Zweig ist hier immer witzlos, egal ob über dem Content-Type oder drunter.

              Sinnvoll wäre er nur, wenn Du den Accept-Header des Browsers vorher abfragen würdest. Wenn Text erwartet wird, muss man auch Text ausgeben und wenn Bilddaten erwartet werden, dann muss mam eben Bilddaten ausgeben. Nur wenn man die Ressource direkt anspricht, könnte es der Browser verkraften...

              Zu Deiner Frage, woran es liegt:

              Was hast Du denn bisher alles untersucht?

              Unterschiedliche Requests aufgebaut?
              Wie rufst Du as Script denn auf?

              An welchen Stellen hast Du bisher schon Testausgaben eingebeut, und welche?
              Testausgaben haben natürlich auch zur Voraussetzung, dass die Antwort verarbeitet (angezeigt) werden kann.

              Harzliche Grüße vom Berg
              http://www.annerschbarrich.de

              Tom

              --
              Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
              Nur selber lernen macht schlau

              1. Also ich habe mal versucht andere Spalten des Datensatzes auszugeben. Ohne Angabe des Content-Types funktioniert das, mit Angabe des Content-Types (Ausgabe vor Content-Type) funktioniert es nicht.

                Also wenn ich das Skript, so wie es ist, direkt aufrufe, kommt die Ausgabe "http://localhost/bild.php".

                Wenn ich die ID übergebe und das Skript mit "http://localhost/bild.php?id=1" aufrufe, kommt auch diese Ausgabe.

                Rufe ich die Datei aus einer anderen Datei mit <img src="bild.php"> bzw. <img src="bild.php?id=1"> auf, kommt ein broken link. Also Bild kann nicht angezeigt werden.

                Grüße Kai!

                1. Hello,

                  Also wenn ich das Skript, so wie es ist, direkt aufrufe, kommt die Ausgabe "http://localhost/bild.php".

                  Wenn ich die ID übergebe und das Skript mit "http://localhost/bild.php?id=1" aufrufe, kommt auch diese Ausgabe.

                  Rufe ich die Datei aus einer anderen Datei mit <img src="bild.php"> bzw. <img src="bild.php?id=1"> auf, kommt ein broken link. Also Bild kann nicht angezeigt werden.

                  Das ist die Folge Deiner ersten Aussage.
                  Ich befürchte, dass der (Denk-)Fehler in den Qracle-Abfragen liegt. Da kann ich Dir aber nicht weiterhelfen, da ich Oracle nicht kenne.

                  Aber Du könntest ja Dein Script mal pingelig genau erklären. Welches Statement bewirkt was bzw. soll was bewirken?

                  Hast Du beim Index [3] auch daran gedacht, dass oci_fetch_row mit [0] anfängt zu zählen? Also steht unter Index [3] die vierte Ergebnisspalte.

                  Harzliche Grüße vom Berg
                  http://www.annerschbarrich.de

                  Tom

                  --
                  Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                  Nur selber lernen macht schlau

                  1. <?php

                    require("./config.php");  // hier stehen einfach die Verbindungsdaten zur Datenbank drin

                    $con = oci_connect($user, $password, $database); // Verbindung zur DB wird hergestellt
                        $sql = "begin p_abfrage.bild_bild(:bild_id, :bild);end;";  // In diesem Package wird eine Abfrage gestartet, die einen kompletten Datensatz (in Form eines Cursors) zurückgibt

                    $curs = oci_new_cursor($con); // Cursor wird angemeldet

                    $result = oci_parse($con, $sql); // Verbindung und Abfrage werden verknüpft und analysiert

                    $ID = 1; // Wert für ID wird zugewiesen um einen bestimmten Datensatz zu bekommen
                       oci_bind_by_name ($result, "bild_id", $ID); // Variable ID wird angemeldet

                    oci_bind_by_name($result, "bild", $curs, -1, OCI_B_CURSOR);
                    // Cursor wird angemeldet

                    oci_execute($result); // Abfrage wird executet
                       oci_execute($curs); // Cursor wird executet

                    $bild = oci_fetch_row($curs); // 1. Reihe des Cursors, also ein Datensatz wird der Variablen zugewiesen

                    Header( "Content-type: Image/jpeg");

                    echo $bild[3];

                    ;
                    ?>

                    ------------------------------------

                    Das war der kommentierte Quelltext. Die Datenbank-Abfrage scheint zu passen. Ja, das Bild ist in der 4. Spalte, also $bild[3]. Alle Werte werden richtig aus der Datenbank gezogen und auch alles richtig ausgegeben, außer halt das Bild. Von daher sehe ich den Fehler weniger in der DB-Abfrage.

                    Mensch, irgendwie muss das doch klappen.... :\

                    1. Hallo,

                      Das war der kommentierte Quelltext. Die Datenbank-Abfrage scheint zu passen. Ja, das Bild ist in der 4. Spalte, also $bild[3]. Alle Werte werden richtig aus der Datenbank gezogen und auch alles richtig ausgegeben, außer halt das Bild. Von daher sehe ich den Fehler weniger in der DB-Abfrage.

                      Der Fehler liegt in der Art, wie Du das LOB aus der Datenbank holen willst. Oracle behandelt LOBs anders als alle anderen Felder. Ferner: Warum verwendest Du überhaupt einen Cursor, obwohl der hier überhaupt nicht notwendig ist?

                      Lies Dir mal folgenden Artikel im Oracle Technet durch: http://www.oracle.com/technology/pub/articles/oracle_php_cookbook/fuecks_lobs.html Dort wird erklärt, wie man LOBs in Oracle und PHP richtig einsetzt.

                      Viele Grüße,
                      Christian

                      --
                      "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
                      1. Hallo,

                        super! Ist schon mal ein konkreter Hinweis. Hab mich mal versucht, aber funzt leider nicht. Hier mein Code:

                        <?php
                        if ($submit){

                        // hier stünden jetzt meine Verbindungsdaten

                        $conn = oci_connect($user, $password, $database);

                        $sql = "INSERT INTO
                                bild
                                  (
                                    bildid,
                                    logo
                                  )
                               VALUES
                                  (
                                    sequence_pk_bild.nextval,
                                    --Initialize as an empty CLOB
                                    EMPTY_BLOB()
                                  )
                               RETURNING
                                  --Return the LOB locator
                                  logo INTO :logo_loc";

                        $stmt = oci_parse($conn, $sql);

                        // Creates an "empty" OCI-Lob object to bind to the locator
                        $myLOB = oci_new_descriptor($conn, OCI_D_LOB);

                        // Bind the returned Oracle LOB locator to the PHP LOB object
                        oci_bind_by_name($stmt, ":logo_loc", $myLOB, -1, OCI_B_BLOB);

                        // Execute the statement using , OCI_DEFAULT - as a transaction
                        oci_execute($stmt, OCI_DEFAULT)
                            or die ("Unable to execute query\n");

                        $BILD = $_POST['form_data'];

                        // Now save a value to the LOB
                        if ( !$myLOB->save('INSERT: '.$BILD) ) {

                        // On error, rollback the transaction
                            oci_rollback($conn);

                        } else {

                        // On success, commit the transaction
                            oci_commit($conn);

                        }

                        // Free resources
                        oci_free_statement($stmt);
                        $myLOB->free();}

                        echo '
                        <html><head></head><body>
                            <form method="post" action="lob.php" enctype="multipart/form-data">
                            <input type="file" name="form_data"  size="40">
                            <p><input type="submit" name="submit" value="submit">
                            </form><br></body></html>';

                        // disconnect from DB etc.
                        ?>

                        ----------------------

                        Das Statement kann nicht ausgeführt werden: "Unable to execute query"

                        Idee woran es liegen könnte? Mit dem Wert der Variablen im Lob speichern müsste doch passen, oder?

  2. Hello,

    Object id #1, wenn ich einfach echo $bild mache.

    Das Bild wird vom Browser über einen eigenen Subrequest angefordert:

    <img scr="http://example.com/bilder/bild2003.jpg" alt="Bild von xy">

    Wie Du nun dafür sorgst, dass dieser Request vom PHP-Parser bearbeitet wird, ist die erste Aufgabenstellung. Man könnte das mittels htaccess (bei Apache) festlegen, oder man benutzt gleich die Rewirte-Engine des Webserver.

    siehe http://httpd.apache.org/docs/2.0/mod/mod_mime.html#addhandler

    Für das Verzeichnis  ~/bilder/ müsstest Du also z.B. festlegen:

    AddHandler get-bild.php .jpg .gif .png

    und ein Script get-bild.php bereitstellen, dass die Anfrage abarbeitet.
    Das Scripüt besorgt sich als erstes den Aufrufparamter (den letzten Teil des Ressource-Name) und entscheidet dann, welches Bild geholt werden soll.

    Es kann dann auch feststellen, ob der User dieses Bild überhaupt erhalten darf, oder ob ein Ersatzbild geliefert werden muss.

    Schließlich beschafft es das Bild aus der Datei oder Datenbank und liefert es mit dem vorangestellten passenden Header aus.

    Da der Browser ein Bild erwartet, kann auch nur ein Bildtyp geliefert werden. Alles andere wäre unsinnig.

    Harzliche Grüße vom Berg
    http://www.annerschbarrich.de

    Tom

    --
    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
    Nur selber lernen macht schlau

  3. Hallöchen,

    Hi

    Object id #1, wenn ich einfach echo $bild mache.

    Ich denke hier liegt der Hund begraben, echo gibt nur strings aus (jedenfalls sagt das php.net) und $bild[3] sind Bild-Daten wenn ich das richtig verstanden habe, also kein String. Wenn $bild[3] eine "resurce" ist und ein Bild, dann musst du es mit
    imagepng($bild[3]);
    imagejpeg($bild[3]);
    oder mit
    imagegif($bild[3]);
    ausgeben (je nachdem was der Server kann und welcher Art die Bilder sind).
    Ich denke dann sollte es gehen.

    Andererseits tendiere ich dazu Bilder nicht direkt in eine Datenbank zu speichern sondern in ein Unterverzeichnis und in die Datenbank dann nur den Verweis (den Dateinamen) darauf. Aber das soll deine Sorge bleiben.

    Wichtig ist eben... mit "echo" kann das eigentlich nicht funktionieren.

    1. Nachtrag: Sollte das nicht klappen kannst du ja die Art der ausgelesenen Daten nochmal via var_dump überprüfen, da sollte dann stehen, ob die Daten als Bild geeignet sind.

    2. echo $begrüßung;

      Object id #1, wenn ich einfach echo $bild mache.
      Ich denke hier liegt der Hund begraben, echo gibt nur strings aus (jedenfalls sagt das php.net) und $bild[3] sind Bild-Daten wenn ich das richtig verstanden habe, also kein String.

      Das kann man so pauschal nicht sagen. Wenn die Bilddaten aus einer MySQL-Datenbank kämen, wären sie von Typ string. Objekte allerdings kann man aber ohne Magie nicht wie ein String ausgeben.

      Wenn $bild[3] eine "resurce" ist und ein Bild,

      Dieser Typ kommt als Ergebnis eines Fetch-Vorgangs nicht vor. Im Allgemeinen sind es Strings. Oracle gibt auch im speziellen Fällen Objekte zurück.

      dann musst du es mit
      imagepng($bild[3]);

      Dazu müsste der Fetch-Vorgang eine Bildressource angelegt haben und wäre auch noch auf das Vorhandensein der Image Functions angewiesen. Das ist aber nicht der Fall.

      Wichtig ist eben... mit "echo" kann das eigentlich nicht funktionieren.

      Oh doch, das geht sogar problemlos für beispielsweise Daten aus BLOB-Feldern von MySQL. Und wenn man die Daten aus einem Oracle-LOB-Objekt befreit hat, liegen sie ebenfalls in einem echo-fähigen String vor.

      echo "$verabschiedung $name";

      1. echo $begrüßung;
        (...)
        echo "$verabschiedung $name";

        Danke für die Belehrung, wieder 'was gelernt. :-)