OnkelOtto: Per htaccess auf zufälliges Bild umleiten

Hallo

Ich habe folgendes Anliegen:
Bein Aufruf der URL http://...../tiere/al101-a.jpg
soll jedes mal ein anderes Bild aus einer Sammlung von 10 verschiedenen Bildern angezeigt werden.

Also, wenn jemand in der Adresszeile seines Browsers die Bild-URL aufruft, soll per Zufall ein Bild aus der Sammlung von 10 Bildern angezeigt werden.

Lässt sich so etwas realisieren?

Gruß
Hubert

  1. Hi,

    Bein Aufruf der URL http://...../tiere/al101-a.jpg
    soll jedes mal ein anderes Bild aus einer Sammlung von 10 verschiedenen Bildern angezeigt werden.
    Also, wenn jemand in der Adresszeile seines Browsers die Bild-URL aufruft, soll per Zufall ein Bild aus der Sammlung von 10 Bildern angezeigt werden.
    Lässt sich so etwas realisieren?

    ja, aber nicht allein über die Serverkonfiguration. Der Apache kennt sowas wie "zufällig" nicht.
    Du kannst aber
     a) unter dem Namen /tiere/al101-a.jpg ein Script ablegen (z.B. PHP) und den Apachen anweisen, das trotz der Endung .jpg als Script auszuführen
    oder
     b) die URL /tiere/al101-a.jpg mit mod_rewrite auf ein Script mit beliebigem Namen umlenken
    und innerhalb dieses Scripts per Zufall ein Bild aus der vorhandenen Menge auswählen, den HTTP-Header "Content-Type: image/jpeg" vorausschicken und die Bilddaten hinterher.

    So long,
     Martin

    --
    Ich stehe eigentlich gern früh auf.
    Außer morgens.
    Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
    1. Hallo Martin

      Ich habe es nun so gemacht:

      <?  
      $_images = array("bild-01.jpg","bild-02.jpg","bild-03.jpg","bild-04.jpg","bild-05.jpg");  
      srand ((double)microtime()*1000000);  
      $r = rand(0,(count($_images)-1));  
      header("Content-Type: image/jpeg");  
      readfile($_images[$r]);  
      ?>  
      
      

      Da es zu funktionieren scheint, gehe ich mal davon aus, dass das korrekt ist.
      Oder kann man da noch was verbessern?

      Gruß
      Hubert

      1. Hallo,

        <?

        $_images = array("bild-01.jpg","bild-02.jpg","bild-03.jpg","bild-04.jpg","bild-05.jpg");
        srand ((double)microtime()*1000000);
        $r = rand(0,(count($_images)-1));
        header("Content-Type: image/jpeg");
        readfile($_images[$r]);
        ?>

        
        > Da es zu funktionieren scheint, gehe ich mal davon aus, dass das korrekt ist.  
          
        sieht mal gar nicht übel aus. Beim Aufruf der rand()-Funktion sind für meinen Geschmack zu viele Klammern im Spiel; den Ausdruck (count($\_images)-1) insgesamt noch zu klammern, ist unnötig. Schädlich ist es aber nicht. ;-)  
          
        
        > Oder kann man da noch was verbessern?  
          
        Ja.  
        Man könnte, nein: sollte! die ausgeschriebene Form anstatt der Short Open Tags verwenden, also "<?php" anstatt "<?". Das vermeidet Ärger, wenn man das Script mal auf einen Server verpflanzt, der die Kurzschreibweise nicht akzeptiert (was recht häufig ist).  
        Schön wäre auch, wenn das Script die zur Verfügung stehenden Bilddateien selbst ermitteln würde - dann könntest du jederzeit welche hinzufügen oder wieder wegnehmen, ohne dass du jedesmal das Script anfassen musst. Die PHP-Funktion [glob()](http://de2.php.net/manual/en/function.glob.php) macht das schon alles, so dass du nur eine einzige Zeile ändern müsstest:  
          
        
        > ~~~php
        
        <?php  
        
        > $_images = glob('bild-??.jpg');  
        > srand ...
        
        

        Viel Spaß noch,
         Martin

        --
        Wenn der Computer wirklich alles kann,
        dann kann er mich mal kreuzweise.
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
        1. $_images = glob('bild-??.jpg');

          OK alles klar.
          Habe das geändert.
          Danke

        2. Hallo Martin,

          bisher wurden alle meine Seite komplett selbst erstellt, also nichts mittels serverseitiger Scripte zusammengebaut. (mein alter Webspace hatte auch kein SSI oder PHP)
          Jetzt lasse ich erstmals eine Bildergalerie (etwa 100 Bilder) mittels PHP generieren.

          Schön wäre auch, wenn das Script die zur Verfügung stehenden Bilddateien selbst ermitteln würde - dann könntest du jederzeit welche hinzufügen oder wieder wegnehmen, ohne dass du jedesmal das Script anfassen musst.

          Dabei stellt sich mir die Frage, ob es wirklich sinnvoll ist, den Server für jeden Seitenaufruf die Bilder neu zusammensuchen zu lassen, nur um die paar Minuten Aufwand zu sparen, die eine Zeile im Script anzupassen, wenn mal ein paar Bilder dazu- oder wegkommen.
          (Um es einigermaßen idiotensicher zu machen, müsste dann ja auch jeweils noch geprüft werden, ob auch wirklich Bild _und_ Thumbnail vorhanden sind.)

          Auf Wiederlesen
          Detlef

          --
          - Wissen ist gut
          - Können ist besser
          - aber das Beste und Interessanteste ist der Weg dahin!
          1. Hallo,

            Schön wäre auch, wenn das Script die zur Verfügung stehenden Bilddateien selbst ermitteln würde - dann könntest du jederzeit welche hinzufügen oder wieder wegnehmen, ohne dass du jedesmal das Script anfassen musst.
            Dabei stellt sich mir die Frage, ob es wirklich sinnvoll ist, den Server für jeden Seitenaufruf die Bilder neu zusammensuchen zu lassen, nur um die paar Minuten Aufwand zu sparen, die eine Zeile im Script anzupassen, wenn mal ein paar Bilder dazu- oder wegkommen.

            die Frage sollte man sich vielleicht wirklich stellen. Und wenn ich ehrlich bin: Ich würde sie unter den gegebenen Bedingungen mit einem entschlossenen "ja" beantworten. Ich mache mit meinem Vorschlag schließlich nur eine Verzeichnissuche, also einen Vorgang, der sowieso "ständig" durchgeführt wird und bei einem sinnvoll organisierten Dateisystem nur Sekundenbruchteile dauern dürfte. Schließlich findet so ein Vorgang quasi nebenbei jedesmal statt, wenn irgendeine Datei geöffnet werden soll.

            (Um es einigermaßen idiotensicher zu machen, müsste dann ja auch jeweils noch geprüft werden, ob auch wirklich Bild _und_ Thumbnail vorhanden sind.)

            Das ist eine neue Situation. Für dein Projekt mit einer Bildergalerie ist das eine sinnvolle Forderung; für die Aufgabenstellung des OP, einfach eines aus n Bildern zufällig auszuwählen, allerdings nicht.

            So long,
             Martin

            --
            Abraham sprach zu Bebraham: Kann i mal dei Cebra ham?
            Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
      2. Hi!

        srand ((double)microtime()*1000000);

        Der Zufallsgenerator muss seit PHP 4.2.0 nicht mehr initialisiert werden, weil PHP dies bereits macht. Bei Zufallszahlen für kryprtografische Zwecke ist die uhrzeitabhängige Initialisierung sogar kontraproduktiv, weil sich die Ergebnisse besser erraten lassen. Die ungefähre Uhrzeit kennt man ja, also weiß man den Wertebereich der Initialisierung, und muss "nur noch die paar Werte" durchprobieren.

        Lo!

        1. Hallo

          Nun sieht das Script so aus:

          <?php  
          $_images = glob('bild-??.jpg');  
          srand ((double)microtime()*1000000);  
          $r = rand(0,count($_images)-1);  
          header("Content-Type: image/jpeg");  
          readfile($_images[$r]);  
          ?>
          

          Habe ich das richtig gemacht?
          Das mit dem Zufallsgenerator habe ich leider noch nicht begriffen.

          Gruß
          Hubert

          1. Hi!

            Das mit dem Zufallsgenerator habe ich leider noch nicht begriffen.

            Du sollst ihn gar nicht initialisieren, weil er von PHP bereits initialisiert wird.

            Wenn er mit srand() initialisiert wird, dann werden seine Werte anhand des übergebenen Arguments berechnet. Der Vorgang ist also nachvollziehbar, wenn der selbe Wert verwendet wird. Das will man im kryptografischen Umfeld nicht, weil man damit leichter einen daraus berechneten Schlüssel nachberechnen kann. Deswegen initialisiert man den Generator besser nicht mit bekannten Größen wie der Uhrzeit sondern mit wesentlich zufälligeren Werten. Das muss aber nicht deine Sorge sein, zumal es bei deinem Verwendungszweck nicht auf die Qualität der Zufallszahl ankommt. Verzichte einfach auf srand().

            srand ((double)microtime()*1000000);

            Zudem ist das auch noch eine Zeile, die sich aus längst vergangenen Zeiten rübergerettet hat. microtime() hat die Angewohnheit, ein recht eigenartiges Format zurückzuliefern. Seit PHP 5 kann man der Funktion deswegen einen optionalen Parameter mitgeben, der dann eine ordentliche Float-Zahl liefert. Wenn du also microtime() irgendwann in anderen Situationen verwenden willst, gib ihr irgendwas, das zu true evaluiert als Parameter mit auf den Weg.

            Habe ich das richtig gemacht?

            Im Rest sehe ich keinen Fehler. Gibt es denn das erwartete Ergebnis oder nicht? Wenn du dir unsicher bist, geh durch den Code und erkläre dir selbst, was er macht[*]. Und das möglichst auch für den Fall, dass ein Fehler auftritt. Dazu musst du dir überlegen, was alles schief gehen kann. Das machen viele leider nicht, woraus dann nicht robuster Code resultiert.

            [*] Am besten ist wohl, wenn du dir jemanden vorstellst, der noch weniger Ahnung hat als du selbst, und ihm verständlich zu erklären versuchst, was dein Code macht. Das schärft auch den Blick für Details.

            Lo!

            1. Hallo,

              Dazu musst du dir überlegen, was alles schief gehen kann. Das machen viele leider nicht, woraus dann nicht robuster Code resultiert.

              eine offensichtliche potentielle Fehlerquelle im vorliegenden Beispiel: Was passiert, wenn überhaupt keine passenden JPEG-Dateien im Verzeichnis gefunden werden? Dann liefert

              $_images = glob('bild-??.jpg');

              ein leeres Array. Das ist nicht weiter schlimm, aber man sollte diese Situation abfragen. Andernfalls würde

              count($_images)-1

              negativ werden und das Ergebnis von

              $r = rand(0,(count($_images)-1));

              undefiniert. Jedenfalls konnte ich keinen Hinweis finden, wie rand() reagiert, wenn $max<$min ist. Aber egal was für $r dabei rauskommt, man greift auf ein nicht existierendes Arrayelement zu:

              readfile($_images[$r]);

              Spätestens hier gibt's eine Notice, weil $_images[$r] nicht existiert, und zusätzlich einen echten Fehler, weil readfile() keinen sinnvollen Dateinamen bekommt.

              [*] Am besten ist wohl, wenn du dir jemanden vorstellst, der noch weniger Ahnung hat als du selbst, und ihm verständlich zu erklären versuchst, was dein Code macht. Das schärft auch den Blick für Details.

              Ja, das ist eine sehr gute Methode, die ich auch gern und oft anwende.

              Ciao,
               Martin

              --
              Ordnung ist, wenn man etwas findet, was man gar nicht sucht.
              Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
    2. Hi!

      soll jedes mal ein anderes Bild aus einer Sammlung von 10 verschiedenen Bildern angezeigt werden.
      Lässt sich so etwas realisieren?
      ja, aber nicht allein über die Serverkonfiguration. Der Apache kennt sowas wie "zufällig" nicht.

      Jein. mod_rewrite kennt eine Zufallsauswahl. Dazu benötigt man aber Zugriff auf die Server- oder VHost-Konfiguration. Die Per-Verzeichnis-Konfiguration (.htaccess) ist nicht ausreichend, weil RewriteMap da nicht mehr will. (Siehe Abschnitt Randomized Plain Text). Die eigentliche RewriteRule kann dann wieder in der .htaccess stehen.

      Lo!

      1. Hallo,

        Der Apache kennt sowas wie "zufällig" nicht.
        Jein. mod_rewrite kennt eine Zufallsauswahl. Dazu benötigt man aber Zugriff auf die Server- oder VHost-Konfiguration. Die Per-Verzeichnis-Konfiguration (.htaccess) ist nicht ausreichend, weil RewriteMap da nicht mehr will. (Siehe Abschnitt Randomized Plain Text).

        das kannte ich tatsächlich noch nicht, danke. Man lernt eben nie aus. :-)
        Dürfte aber, wie du selbst schon einräumst, für die meisten Hosting-Kunden nicht in Frage kommen, wenn man es nicht in der lokalen Konfiguration einrichten kann.

        Ciao,
         Martin

        --
        Okay, Alkohol ist keine Antwort.
        Aber manchmal vergisst man beim Trinken wenigstens die Frage.
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(