Jörn: Fotos/Bilder in MySQL Datenbank

Hallo Leute. Kann man eigentlich zu einem Datensatz in einer MySQL Tabelle ein Bild oder ein Foto speichern? Man könnte sich ja vorstellen, daß man eine Liste ausgibt und zu jedem Datensatz ist zusätzlich eine Spalte mit einem link oder so etwas, daß dann das dazugehörige Foto öffnen kann.
Und wenn ja, gibt es irgendwo Seiten, wo so etwas beschrieben ist?
Programmieren tue ich mit PHP.
Dank im voraus.
Jörn

  1. Hallo Jörn.

    Direkt in der DB kannst Du keine Bilder speichern. Du kannst aber Dateinamen speichern (bzw. generieren) und alle Bilder in einem Verzeichnis speichern. Somit kann jeder Datensatz ein Bild enthalten, die Daten des Bildes bleiben aber außerhalb der DB selbst.

    Grüße aus Würzburg
    Julian

    1. Hallo!

      Direkt in der DB kannst Du keine Bilder speichern.

      Sicher geht das, Du kannst auch binäre Daten in der DB speichern, in den mir bekannten zumindest!

      Grüße
      Andreas

  2. Moin!

    Hallo Leute. Kann man eigentlich zu einem Datensatz in einer MySQL Tabelle ein Bild oder ein Foto speichern? Man könnte sich ja vorstellen, daß man eine Liste ausgibt und zu jedem Datensatz ist zusätzlich eine Spalte mit einem link oder so etwas, daß dann das dazugehörige Foto öffnen kann.

    Es gibt zwei Möglichkeiten:

    1. Du speicherst die binären Daten des Bildes in einem BLOB-Feld. Dann benötigst du aber zum Anzeigen des Bildes im Browser ein weiteres PHP-Skript, welches das Bild aus der Datenbank ausliest und anzeigt. Außerdem wird die Datenbank dadurch ziemlich groß und voll.

    2. Du speicherst das Bild als Datei auf der Festplatte, gibst ihm ggf. einen eindeutigen Namen (verwende gerne die Datensatz-ID dazu), und speicherst, falls notwendig, den Dateinamen als String in der Datenbank. Dann benötigst du kein extra PHP-Skript zum Bild-Auslesen, sondern kannst einfach den IMG-Link ausgeben, und der Server liefert dann automatisch das Bild dazu. Das spart auch Traffic, weil der Browser und zwischengelagerte Proxys das Bild cachen können - das müßtest du mit deinem Extra-Skript sonst selbst regeln.

    - Sven Rautenberg

    1. Hallo,

      ... und die dritte Möglichkeit ist, dass Du in der Datenbank nur den Link auf das Bild (also einen verweis auf seinen Speicherort = Pfad und Name) speicherst und trotzdem ein Skript zum Ausgeben des Bildes zwischenschaltest.

      Warum?

      Ganz einfach: alle Bilder, die direkt über einen <img src="bla"> Link erreichbar sind, können auch von "Unbefugten" von der Platte gesaugt werden. Du hast also keinerlei Kontrolle über die Zugriffe.

      Mein Wunsch wäre es daher, die Bilder in einem für den "Normalsurfer" unzugänglichen Verzeichnis außerhalb der Document-Root zu speichern.

      Thoralf Knuth hatte mir zu diesem Zwweck mal ein Skript gepostet. Ich gebe es einfach mal so wieder:

      "------
      Hallo Thomas,

      ich poste Dir einfach mal ein Script, was ich seit einer Weile ohne Probleme verwende. Eigentlicher Zweck ist bei mir eine rudimentäre Referer-Kontrolle zur Traffic-Schonung, aber das sollte sich leicht auf Deine Bedürfnisse umstellen lassen.

      Dabei ist /grafiken/versteckt/ per .htaccess gesperrt, kann aber natürlich auch ein Pfad ausserhalb der DOCROOT sein.

      Ich hab die für Dich unwesentlichen Teile durch /* ... */ ersetzt. Alle entscheidenden Punkte sind vorhanden.

      <?php

      Standard-Aufruf: bild.php?bild=/grafiken/versteckt/bild.jpeg

      error_reporting( E_ALL );
      $DOCUMENT_ROOT = getenv( 'DOCUMENT_ROOT' );

      $nicht_gefunden_pfad = $DOCUMENT_ROOT . '/images/404.jpg';
      $falscher_referer_pfad = $DOCUMENT_ROOT . '/images/403.jpg';

      $header_gif  = 'Content-type: image/gif';
      $header_jpeg = 'Content-type: image/jpeg';
      $header_png  = 'Content-type: image/png';

      $HTTP_REFERER = getenv( 'HTTP_REFERER' );
      $referer_ok  = false;

      $allowed_referers = array(
        /* ... */
      ); # $allowed_referers = array(

      Wurde ein Bild uebergeben?

      if( ! isset( $bild ) OR $bild == '' )
      {
        header( $header_jpeg );
        readfile( $nicht_gefunden_pfad );
        return;
      } # if( ! isset( $bild ) OR $bild == '' )

      Soll der Referer gecheckt werden? Wenn denn einer vorhanden ist ;)

      if( ! isset( $bild_php_kein_referer_check ) AND $HTTP_REFERER != '' )
      {
       /* Code, um den Referer zu checken */
      }
      else # if( ! isset( $bild_php_kein_referer_check ) )
      {
        $referer_ok = true;
      }

      Referer ok?

      if( ! $referer_ok )
      {
        header( $header_jpeg );
        readfile( $falscher_referer_pfad );
        return;
      } # if( ! $referer_ok )

      $datei_uri  = str_replace( '//', '/', '/vorgegebenes_verzeichnis/'. urldecode( $bild ) );
      $datei_pfad = $DOCUMENT_ROOT . $datei_uri;

      Gibt es das Bild?

      if( ! file_exists( $datei_pfad ) )
      {
        header( $header_jpeg );
        readfile( $nicht_gefunden_pfad );
        return;
      } # if( ! file_exists( $datei_pfad ) )

      Korrekten Header senden

      switch( strtolower( $datei_pi['extension'] ) )
      {
        case 'gif':
          header( $header_gif );
          break 1;
        case 'png':
          header( $header_png );
          break 1;
        case 'jpg':
        case 'jpeg':
        default:
          header( $header_jpeg );
          break 1;
      } # switch

      Letzte Aenderung durchreichen

      if( ! isset( $last_modified ) OR $last_modified == '' )
      {
        $datei_zeit = filemtime( $datei_pfad );
        header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s', $datei_zeit ) . ' GMT' );
      }
      else
      {
        header( $last_modified );
      }

      Soll der korrekte Name zum Speichern mit angegeben weren? Eigentlich ja, aber zB bei naechster_hthumb.php nicht

      if( ! isset( $bild_php_dont_give_name ) )
      {
        header("Content-Disposition: attachment; filename="" . basename( $datei_pfad ) . """);
      }

      readfile( $datei_pfad );
      return;
      ?>

      Gruss, Thoralf
      -----" (Zitat Ende)

      Ich hoffe, es nützt Dir auch. Ich habs selber leider noch nicht angefasst, aber mein Nachwuchskollege meint, es geht super.

      Grüße

      Tom

      1. Moin!

        ... und die dritte Möglichkeit ist, dass Du in der Datenbank nur den Link auf das Bild (also einen verweis auf seinen Speicherort = Pfad und Name) speicherst und trotzdem ein Skript zum Ausgeben des Bildes zwischenschaltest.

        Warum?

        Ganz einfach: alle Bilder, die direkt über einen <img src="bla"> Link erreichbar sind, können auch von "Unbefugten" von der Platte gesaugt werden. Du hast also keinerlei Kontrolle über die Zugriffe.

        Schwachsinnsbegründung! Alle Bilder, die per URL erreichbar sind, können gesaugt oder auf fremden Seiten verlinkt werden. Es ist dabei total unerheblich, ob ein Skript oder der Webserver selbst irgendwelche Prüfungen ausführen oder nicht. Wichtig ist nur: Das Bild ist unter http://www.example.com/irgendeinpfad/irgendein-skript.name?mit=irgendeinem&parameter=gequassel weltweit verfügbar - warum durch Aufruf dieser URL ein Bild kommt, ist für den Browser nicht weiter interessant. Aber für den Server, der bei direkt auf Platte gespeicherten Bildern Caching-Mechanismen wirksam werden lassen kann, die bei jeglicher Script-Einwirkung nicht mehr möglich sind - es geht also immer auf Kosten der Performance.

        Wenn nur ein simpler Referrer-Check erfolgen soll, dann kann man das genauso schön auch durch entsprechende Konfiguration des Apache-Servers erreichen, beispielsweise durch mod_rewrite, was im Vergleich zu einem PHP-Skript immer noch wesentlich performanter sein dürfte.

        - Sven Rautenberg

        1. Hallo Sven,

          Ganz einfach: alle Bilder, die direkt über einen <img src="bla"> Link erreichbar sind, können auch von "Unbefugten" von der Platte gesaugt werden. Du hast also keinerlei Kontrolle über die Zugriffe.

          Schwachsinnsbegründung! Alle Bilder, die per URL erreichbar sind, können gesaugt oder auf fremden Seiten verlinkt werden. Es ist dabei total unerheblich, ob ein Skript oder der Webserver selbst irgendwelche Prüfungen ausführen oder nicht.

          Jetzt bin ich aber enttäuscht! Ich dachte immer, die Auth-Methoden und Sessions in PHP funktionieren immer. Gehen die denn nicht, wenn man Bilder ausgibt? Woran erkennt PHP denn, dass es jetzt nicht um den Inhalt des Datensatzes, sondern um ein darin referenziertes Bild geht? Das versteh ich jetzt nicht.

          Und wie willst Du mit HTTP an die Bilder auf meinem Server rankommen, die in einem Verzeichnis außerhalb der Document-Root stehen? Soll ich schon mal die Kripo anrufen? :-))

          Grüße aus http://www.braunschweig.de

          Tom

          1. Hi!

            Ist das eigentich so schwer zu begreifen? Wenn Du willst das ein User im Browser ein Bild angezeigt bekommt, dann muß dieses Bild bevor es angezeigt wird als Datei im Temporären Ordner des Browsers gespeichert werden. Was auch immer Du vorher für Verränkungen anstellst - das kann man nicht schützen! Vielleicht gegen ein paar Stümper die keine Ahnung haben oder Leute die sich Ihre Webseiten grundsätzlich zusammenklauen, aber selbst die können nicht soooo doof sein. Das einzige was Dir diese Methode bringt wenn ich es richtig verstanden habe, das eine Fremde Webseite die Bilder nicht direkt verlinken kann. Aber auch das läßt sich spielen mit einem kleinen PHP-Script umgehen, denn mit PHP, PERL und vielen anderen Sprachen und kleinen Tools kannst Du einen Browser vollständig emulieren, Du kannst machen was Du woillst, solange die Bilder über Deine Homepage frei zugänglich sind kommt man da auch ran. Wobei man wie gesagt mit einigen Methoden einigen Leute Steine in den Weg legen kann, aber mehr auch nicht.

            Jetzt bin ich aber enttäuscht! Ich dachte immer, die Auth-Methoden und Sessions in PHP funktionieren immer. Gehen die denn nicht, wenn man Bilder ausgibt? Woran erkennt PHP denn, dass es jetzt nicht um den Inhalt des Datensatzes, sondern um ein darin referenziertes Bild geht? Das versteh ich jetzt nicht.

            Ich verstehe Deine Frage nicht. Die "Authentifizierung" - wenn man das so nennen kann - die in dem geposteten Script vorgenommen wird, ist in der tat ohne wien wenig Programmierkenntnisse kaum zu überwinden. Aber wie gesagt - mit - kein Problem. Auch die Sessions bringen nichts da man die sich auch automatisch holen kann.
            Und was hat das mit dem referenzierten Bild zu tun? PHP ist doch egal was in der DB steht! Das Script erzeugt halt Header und schickt dann die Binärdaten des Bildes, so das der Browser denkt es handele sich um ein "echtes" Bild, wo liegt das Problem?

            Und wie willst Du mit HTTP an die Bilder auf meinem Server rankommen, die in einem Verzeichnis außerhalb der Document-Root stehen?

            Wieso? Das machst Du doch bereits für uns ;-) Wie bereits gesagt, wenn Di bilder nur im Document Root liegen und Du kein Script hast um diese auszugeben dann wird Sie außer Dir keiner zu Gesicht bekommen. Wäre wohl die sicherste Variante. Die nächst sichere wäre die Bilder in ein .htaccess geschütztes Verzeichnis zu legen und nur bestimmten User Zutritt zu vverschaffen, aber selbst da ist fraglich ob Du das willst! Wenn Du willst das alle die Bilder ohne Beschränkung sehen können, dann kann es auch jeder Browser, und wenn es automatisiert sein soll, dann lassen wir PHP & Co. halt so tun als seien sie Browser!

            Soll ich schon mal die Kripo anrufen? :-))

            Au ja! Das wird die sicher interessieren!

            Viele Grüße
            Andreas

            1. Hallo Andreas,

              nun lass mal die Luft ganz vorsichtig wieder ab und komm ganz langsam wieder auf den Teppich zurück. Du bist auf dem falschen Dampfer gelandet...

              Ich lasse den langen Text jetzt mal drin.

              Ist das eigentich so schwer zu begreifen? Wenn Du willst das ein User im Browser ein Bild angezeigt bekommt, dann muß dieses Bild bevor es angezeigt wird als Datei im Temporären Ordner des Browsers gespeichert werden. Was auch immer Du vorher für Verränkungen anstellst - das kann man nicht schützen! Vielleicht gegen ein paar Stümper die keine Ahnung haben oder Leute die sich Ihre Webseiten grundsätzlich zusammenklauen, aber selbst die können nicht soooo doof sein. Das einzige was Dir diese Methode bringt wenn ich es richtig verstanden habe, das eine Fremde Webseite die Bilder nicht direkt verlinken kann. Aber auch das läßt sich spielen mit einem kleinen PHP-Script umgehen, denn mit PHP, PERL und vielen anderen Sprachen und kleinen Tools kannst Du einen Browser vollständig emulieren, Du kannst machen was Du woillst, solange die Bilder über Deine Homepage frei zugänglich sind kommt man da auch ran. Wobei man wie gesagt mit einigen Methoden einigen Leute Steine in den Weg legen kann, aber mehr auch nicht.

              Es geht nicht um einen "Kopierschutz" für ausgelieferte Bilder, sondern es geht um einen Zugriffsschutz für noch auszuliefernde Bilder. Haaalt! Luft holen, bis zehn zählen, Gehirn einschalten :-))

              Dämmert es nun langsam?

              Es gibt durchaus Bilddatenbanken, in denen die Nutzer für die Info bezahlen, oder in denen ein gewisser Datenschutz der Nutzer gegeneinander gewährleistet sein muss. Das kann man eben nur mit
              a) in der Datenbank gepeicherten Bildern
              b) in einm geschützten Verzeichnis gespeicherten Bildern

              erreichen.

              In beiden Fällen ist das DAI dafür zuständig, die Rechte des Anfragenden zu prüfen und dann ggf. auszuliefern, auszutauschen oder zu verweigern.

              Und was hat das mit dem referenzierten Bild zu tun? PHP ist doch egal was in der DB steht! Das Script erzeugt halt Header und schickt dann die Binärdaten des Bildes, so das der Browser denkt es handele sich um ein "echtes" Bild, wo liegt das Problem?

              Genau, und weil es sich um ein Script handelt (im Beispiel fehlt natürlich der Auth-Teil, aber den sollte man sich ja selber dazu denken können) kann vom Script eine Authentifizierung vorgenommen werden. Die Zugriffsdaten können sogar in der Datenbank stehen.

              Und wie willst Du mit HTTP an die Bilder auf meinem Server rankommen, die in einem Verzeichnis außerhalb der Document-Root stehen?

              Wieso? Das machst Du doch bereits für uns ;-) Wie bereits gesagt, wenn Di bilder nur im Document Root liegen und Du kein Script hast um diese auszugeben dann wird Sie außer Dir keiner zu Gesicht bekommen. Wäre wohl die sicherste Variante.

              Nein, das wäre nicht sicher. Mit einer geeigneten Scan-Anfrage kann man das gesamte Verzeichnis auslesen, wenn die Rechte für ein normales <img src="..."> eingestellt sind.

              Die nächst sichere wäre die Bilder in ein .htaccess geschütztes Verzeichnis zu legen und nur bestimmten User Zutritt zu verschaffen, aber selbst da ist fraglich ob Du das willst!

              Nein, das habe ich auch nicht gemeint. Das wäre ein viel zu großer Verwaltungsaufwand, für jeden User die Files per .htaccess zu signieren. Das geht zwar, .htaccess ist aber von seiner Art her (eher) ein _Verzeichnisschutz_ und kein Schutz für einzelne Files.

              Wenn Du willst das alle die Bilder ohne Beschränkung sehen können, dann kann es auch jeder Browser, und wenn es automatisiert sein soll, dann lassen wir PHP & Co. halt so tun als seien sie Browser!

              Darum ging es ja gerade, das _nicht_ alle Leute alle Bilder sehen dürfen, sondern nur bestimmte Leute bestimmte Bilder, und das vielleicht täglich wechslend und in überschneidenden Mengen.

              Soll ich schon mal die Kripo anrufen? :-))
              Au ja! Das wird die sicher interessieren!

              Klar interessiert die das, wenn sich jemand zu geschützten Daten wiederrechtlich Zugang verschafft. Das ist eine Straftat, die zwischen fünf und 15 Jahren ### einbringt.

              So, nun hoffe ich, dass klar ist, worum es hier ging.
              Noch ein Wort in eigener Sache: Ich gehöre nicht zu den Leuten, die im Internet die Methode "meins, meins..." propagieren, sondern zu denen, die gerne Erfahrungen und Ergebnisse teilen. Trotzdem kann die Aufgabenstellung ja Datenschutz verlangen - oder?

              Nun leg dich wieder hin :-))

              Liebe Grüße aus http://www.braunschweig.de

              Tom

              1. Hi!

                Naja, wenn das so ist, dann habe ich mich wohl geirrt, wobei das nicht wirklich aus den Postings hervorging, aber vielleicht bin ich tatsächlich etwas müde ;-)
                Die Lösungen wurden doch schon gepostet!
                Eine Tabelle mit der BildID und dem Pfad oder besser nur mit dem Dateinamen, wenn alle Bilder im selben Pfad liegen, dann eine Tabelle mit Usern, und eine Tabelle mit Rechten. Wenn User A Zugriffsrechte auf Bilder 3, 26 und 67 haben soll, dann schreibst Du in die Tabelle "Rechte" 3 Datensätze

                UserID | BildID
                -------+-------
                A      | 3
                A      | 26
                A      | 67

                Wenn Du dem User A dann alle seine Bilder anzeiegn willst, könntst Du die Dateinamen wie folgt aus der DB holen(ungetestet):

                SELECT
                        Bilder.Dateiname
                    FROM Rechte
                    LEFT JOIN Bilder
                        ON Rechte.BildID = Bilder.BildID
                    WHERE Rechte UserID = 'A'

                Dann nimmst Du das Script was Du schon hattest und holst Dir mit dem Dateinamen das Bild aus dem document Root oder woher auch immer. Und wenn für den User keine Rechte gespeichert sind mußt Du ihn halt vorher ablehnen...

                Grüße
                Andreas

                1. Noch higher...

                  Mööönsch, genau so!
                  jetzt werde ich mir Dein Posting gleich noch dazu abspeichern und morgen mal ein Testprogramm aus beiden Teilen zusammenkleben.

                  Schöne Nachtruhe wünsche ich.

                  Tom