BLOB Image aus mysql auslesen und anzeigen lassen

klwild

Grünschnabel
Hallo zusammen.

Ich habe eine komplettes Umstrukturieren meines HTML/PHP Seite hinter mir: Einzelne kleine Bilder über 'grosses' Grid legen? (Grundsatzfrage) Danke noch mal dem Forum dafür, es ist alles viel leichter und einfacher geworden.

Letztes Problem ist das ich ein BLOB Bild aus er Datenbank auslesen und anzeigen muss. Hier im Forum stehen die verschiedensten Sachen, aber nichts hilf wirklich.

BLOB-Image.png

Hier der Code den ich verwende (BLOB: $adds[$i][5]):
PHP:
    $adds = array();

    $sql = "SELECT * FROM htzu_adds WHERE id > 0 AND status = 'A' ORDER BY id ASC";
   
    $result = $mysqli->query($sql);
    foreach ($result as $row) {
        $adds[] = array($row["id"], $row["status"], $row["name"], $row["slogan"], $row["link"], $row["image"], $row["posX"], $row["posY"], $row["witdh"], $row["height"]);
    };   

    $i = 0;
    for($i=0; $i<count($adds); $i++) {
        echo "<a href='".$adds[$i][4]."' target='_blank' title='".$adds[$i][3]."' />";
        //echo "<img src='".$adds[$i][5]."' width='".$adds[$i][8]."' height='".$adds[$i][9]."' style='position:fixed; left:".$adds[$i][6]."px; top:".$adds[$i][7]."px;' />";
        echo "<img src='data:image/png;base64,'".base64_encode($adds[$i][5])."' width='".$adds[$i][8]."' height='".$adds[$i][9]."' style='position:fixed; left:".$adds[$i][6]."px; top:".$adds[$i][7]."px;' />";
        echo "</a>";
    };

    $mysqli->close();
?>

Danke Klaus
 
Zuletzt bearbeitet von einem Moderator:
Warum hast du Bilder in der Datenbank? Siehe FAQ der Newsgroups de.comp.lang.php.* - 16.3. Ist es sinnvoll, Bilder in einer Datenbank abzulegen?
Warum schreibst du Select *? Siehe FAQ der Newsgroups de.comp.lang.php.* - 16.14. Warum soll ich nicht SELECT * schreiben?
Warum speicherst du das Array $row als Array in einem Array?
Warum postest du Quellcode ohne die Formatierungsmöglichkeiten des Forums zu benutzen?

1683989303092.png


Richtig debuggen
  1. Man bemerkt, dass ein Skript nicht das tut, was es soll.
  2. Man schreibt an den Anfang des Scriptes die Zeile: error_reporting(-1);
  3. Man verwendet ini_set('display_errors', true); damit die Fehler auch angezeigt werden.
  4. Man versucht, die Stelle die daran Schuld sein kann, schonmal einzugrenzen. Falls dies nicht geht, wird zunächst das komplette Skript als fehlerhaft angesehen.
  5. An markanten Stellen im Skript lässt man sich wichtige Variableninhalte ausgeben und ggf. auch in bedingten Anweisungen eine kurze Ausgabe machen, um zu überprüfen, welche Bedingung ausgeführt wurde. Wichtig bei MySQL Fehlern (...not a valid MySQL result resource...): mysqli_error() verwenden oder Abfrage ausgeben und zb mit phpmyadmin testen.
  6. Schritt 5 wird so lange wiederholt, bis Unstimmigkeiten im Skript auffallen
  7. Damit hat man das Problem (Unstimmigkeit) gefunden und kann versuchen diese zu beheben. Hierzu dienen dann die PHP-Dokumentation und andere Quellen als Ratgeber.
  8. Lässt sich das konkrete Problem trotzdem nicht beheben, kann man in Foren um Rat fragen.
  9. Das Programm läuft und man kann die Debug-Ausgaben wieder entfernen.
 
Anstatt eine Lösung dafür zu suchen, wäre es nicht schlecht, wenn du diese Frage beantworten würdest:

Warum hast du Bilder in der Datenbank?
 
Es gibt dann tausende kleine Bilder, wobei man in im Filesystem schnell die Übersicht verliert. Darum die DB.

Es läuft so weit, so gut bis auf Kleinigkeiten (hoffe ich):

1. Wenn ich die Funktion: public function selectBlob($id) { setzten will meckert das System über public
2. Objekt erstellen geht $blobObj = new BlobAdd(); aber $a = $blobObj->selectBlob(1); mach Fehler: selectBlog not found.

3. Ich habe den ganzen Code, den ich brauche in eine blob.php geschrieben und hoffe das ist nicht der Fehler.

PHP:
<?php

/**
 * PHP MySQL BLOB Add
 */
class BlobAdd {

    const DB_HOST = 'localhost';
    const DB_NAME = 'hunderttausend-zuger-unternehmen';
    const DB_USER = 'root';
    const DB_PASSWORD = '';

    /**
     * Open the database connection
     */
    public function __construct() {
        // open database connection
        $conStr = sprintf("mysql:host=%s;dbname=%s;charset=utf8", self::DB_HOST, self::DB_NAME);

        try {
            $this->pdo = new PDO($conStr, self::DB_USER, self::DB_PASSWORD);
            //for prior PHP 5.3.6
            //$conn->exec("set names utf8");
        } catch (PDOException $e) {
            echo $e->getMessage();
        }
    }

    /**
     * close the database connection
     */
    public function __destruct() {
        // close the database connection
        $this->pdo = null;
    }

}

/**
     * update the files table with the new blob from the file specified
     * by the filepath
     * @param int $id
     * @param string $filePath
     * @param string $mime
     * @return bool
     */
    function updateBlob($id, $filePath, $mime) {

        $blob = fopen($filePath, 'rb');

        $sql = "UPDATE htzu_adds
                SET image = :data
                WHERE id = :id;";

        $stmt = $this->pdo->prepare($sql);

        $stmt->bindParam(':data', $blob, PDO::PARAM_LOB);
        $stmt->bindParam(':id', $id);

        return $stmt->execute();
    }
    
/**
     * select data from the the files
     * @param int $id
     * @return array contains mime type and BLOB data
*/     
    public function selectBlob($id) {

        $sql = "SELECT 'image/png',
                        data
                   FROM  htzu_adds
                  WHERE id = :id;";

        $stmt = $this->pdo->prepare($sql);
        $stmt->execute(array(":id" => $id));
        $stmt->bindColumn(1, $mime);
        $stmt->bindColumn(2, $data, PDO::PARAM_LOB);

        $stmt->fetch(PDO::FETCH_BOUND);

        return array("data" => $data);
    }
 
Bin nicht so der Experte für OOP aber ich sehe da folgendes:

1. Die Funktionen updateBlob und insertBlob liegen außerhalb der Definition der Klasse, daher ist "public" nicht möglich und $this ist unbekannt. Also die schließende Klammer in Zeile 37 ganz an das Ende verschieben.

2. Das $this->pdo braucht offenbar eine Deklaration:
Code:
class BlobAdd
{
    const DB_HOST = 'localhost';
    const DB_NAME = 'hunderttausend-zuger-unternehmen';
    const DB_USER = 'root';
    const DB_PASSWORD = '';
    private $pdo;
    /**
     * Open the database connection
     */
    public function __construct()
    {
        // open database connection
        $conStr = sprintf("mysql:host=%s;dbname=%s;charset=utf8", self::DB_HOST, self::DB_NAME);
        try {
            $this->pdo = new PDO($conStr, self::DB_USER, self::DB_PASSWORD);
            //for prior PHP 5.3.6
            //$conn->exec("set names utf8");
        } catch (PDOException $e) {
            echo $e->getMessage();
        }
    }
Ändere ich beides, zeigt zumindest mein Visual-Studio-Code keine Fehler mehr an.
 
@bdt600
In dem Artikel, den Du verlinkt hast, finden sich nicht nur Gründe, die gegen das Speichern von Bildern in der DB sprechen sondern auch einer dafür:
Wenn man die Bilddaten selbst in der Datenbank ablegt, hat dies den Vorteil, dass keine broken links auftreten können, weil ja die Bilder selbst genauso wie die Links auf die Bilder aus der Datenbank erzeugt werden. Liegen die Bilddaten dagegen im Dateisystem und die Datenbank enthält nur Pfadnamen, dann ist es problemlos möglich, dass jemand die Dateien umbenennt, ohne diese Änderung in der Datenbank nachzuführen und umgekehrt.
Aus dem Code im Eingangsposting von @klwild ist ersichtlich, dass neben den Bildern selbst noch diverse andere Parameter gespeichert sind, die dem Bild unmittelbar zugeordnet sind. Ist dass alles in einem Datensatz gespeichert, ist die Konsistenz sicher gestellt. Wollte man das Bild im Dateisystem ablegen müsste man eine Referenz darauf in der Datenbank ablegen und diese haben die Angewohnheit, dass das Ziel irgend wann nicht mehr gefunden wird und sie ins Leere führt.

Weiter steht in dem verlinkten Artikel:
Wenn man die Bilddaten selbst in der Datenbank speichert, dann muss man für jedes Bild in einer Webseite ein Script starten.
Für den Code von @klwild trifft das gar nicht zu, denn er ruft die Bilder nicht einzeln jeweils durch ein Skript ab sondern trägt sie in einer Schleife base64-kodiert in das HTML ein. D. h. dieser Einwand trifft gar nicht zu.

MySQL kann BLOBs (binary large objects) nicht fragmentarisch bearbeiten, d.h. es ist nicht möglich, ein BLOB in kleinen Teilstücken aus der Datenbank zu holen oder den hinteren Teil eines BLOBs zu holen, ohne die Bytes davor zu lesen.
Ich war noch nie mit der Notwendigkeit konfrontiert, Bilder fragmentarisch zu bearbeiten, d. h. dieser Einwand ist weit entfernt von der Praxis, jedenfalls wenn es um Bilder geht.

Und, BTW: Immer wenn es darum geht, Daten auf dem Server zu speichern, kommt reflexhaft: "Du musst dafür unbedingt eine Datenbank einsetzen". Und jetzt auf ein Mal eine Kehrtwende "Speichere das auf keinen Fall in der Datenbank"? :oops:
 
Zurück