Flo: Internet Explorer erzeugt Fehler in meiner Galerie

Hallo,

ich habe heute abend die 2. Version meiner Internet Seite (mehr oder weniger) fertig gestellt (wann ist eine Seite schon fertig...)!
Beim Testen gibt es beim Internet Explorer allerdings ein ziemliches Problem.
Auf meiner Seite befinden sich eine Menge Fotos von Fußballspielen, natürlich sortiert nach Spielen. Klickt man ein Spiel an, so werden alle Fotos dieses Spiels angezeigt und man kann, um eine größere Version des Fotos zu sehen auf das jeweilige Foto klicken.
Von dieser größeren Ansicht aus kann man "vorwärts" und "rückwärts" durch die Bilder schalten. Mit dem Mozilla Firefox geht das auch problemlos. Wenn ich jedoch beim Internet Explorer auf "vorwärts" oder "rückwärts" klicke, dann passiert gar nichts. Die Seite wird zwar neu geladen, das entsprechende Bild wird aber nicht angezeigt. Ich habe dann mal testweise den Pfad ausgeben lassen auf das Bild. Der Pfad wird auch korrekt angezeigt, d.h. wenn ich auf "vorwärts" geklickt habe, dann verweist der Pfad auf das nächste Bild, klicke ich nochmal, auf das übernächste etc. Wenn ich nun aber F5, also aktualisieren drücke, dann wird das Bild korrekt angezeigt?!

Hier ist der Link zur Galerie. Wie gesagt tritt das Problem nur beim Internet Explorer auf:
http://neoflo.ne     .funpic.de/galerie.php   (ohne Leerzeichen natürlich)

Hier auch noch das Skript, welches das Foto anzeigt und vor- bzw. zurückschaltet:

$id = $_GET['id'];
$no = $_GET['no'];
if ($no < 10)
{
 $no = "0".$no;
}
$sql = "SELECT * FROM galerie WHERE id=$id";
$result = mysql_query($sql, $conn);
if ($result)
{
 while ($row = mysql_fetch_row($result))
 {
  $bild = $row[4].$no.".JPG";
  $size=getimagesize($bild);
  $newwidth = 700;
  $newheight = 525;
  $oldimage = ImageCreateFromJPEG($bild);
  $newimage=imagecreatetruecolor($newwidth,$newheight);
  ImageCopyResized($newimage, $oldimage, 0, 0, 0,
                0,$newwidth, $newheight, $size[0], $size[1]);
  ImageJPEG($newimage, "image_neu.JPG");
  echo "$bild";
  echo "<img src='image_neu.JPG' style='border: 2px
                solid #C20000'>";
  ImageDestroy($newimage);
  ImageDestroy($oldimage);
  $no_vor = $no + 1;
  $no_rueck = $no - 1;
  echo "<ul class='uebersicht'>";
  if ($no != 1)
  {
   echo "<li> <a
                        href='showFoto.php?id=$id&no=$no_rueck'> <img
                        src='./img/prev.jpeg 'alt='vorheriges'
                        style='border-color: black'> </a> </li>";
  }
  echo "<li> <a href='showFotos.php?id=$id'> <img
                src='./img/overview.jpeg' alt='zur &Uuml;bersicht'
                style='border-color: black'> </a> </li>";
  if ($no != $row[5])
  {
   echo "<li> <a
                        href='showFoto.php?id=$id&no=$no_vor'> <img
                        src='./img/next.jpeg 'alt='n&auml;chstes'
                        style='border-color: black'> </a> </li>";
  }
  echo "</ul>";
        }
}

Ich hoffe es ist deutlich geworden wo das Problem ist!

Schon mal vorab vielen Dank für die Hilfe und das viele Lesen! ;)

Mfg Florian

  1. Hi,

    Beim Testen gibt es beim Internet Explorer allerdings ein ziemliches Problem.

    für clientseitige Probleme ist serverseitiger Code nicht nur vollkommen irrelevant, sondern störend.

    Cheatah

    --
    X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
    X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
    X-Will-Answer-Email: No
    X-Please-Search-Archive-First: Absolutely Yes
    1. Hi,

      Beim Testen gibt es beim Internet Explorer allerdings ein ziemliches Problem.

      für clientseitige Probleme ist serverseitiger Code nicht nur vollkommen irrelevant, sondern störend.

      Cheatah

      Wo soll der Fehler sonst liegen, wenn nicht in dem Teil des Programms?

      Was die Sache mit dem Cache angeht:
      Das ist sicher eine Möglichkeit, aber wie kann ich das denn vermeiden?
      ich kann ja nicht jedesmal einen anderen Dateinamen für das Bild verwenden, weil ich das jeweilige Bild nur temporär verkleinern möchte!

      1. Die Bilder werden ja (wenn ich das richtig verstanden habe) durch die Kombination von $id und $no eindeutig identifiziert. Daraus kannst Du dann den Namen bilden. Die verkleinerten Versionen der Bilder kannst Du dynamisch erzeugen, indem Du z.B. Skripte für folgende URL-Struktur machst:
        http://neoflo.ne.funpic.de/thumbnail.php?id=10&no=8
        http://neoflo.ne.funpic.de/image.php?id=10&no=8
        Die erste URL ruft die Miniaturansicht eines Bildes ab, die zweite die Originalgröße. Die beiden Skripte können die Bilder ggf. dynamisch erzeugen. Das zweite Skript kann aber auch einfach die entsprechende Datei zurückgeben. Dadurch hast Du eine einheitliche Benennung, und es kann keine Cachekonflikte mehr geben, da jedes Bild und jede Miniaturansicht ihre eigene URL hat. Die URLs lassen sich auch einfach in die skriptgenerierte HTML Seite integrieren, da Du $id und $no der Bilder immer kennst bzw. an die nächste Seite weitergibst.

        MfG
        GK

        1. Die Bilder werden ja (wenn ich das richtig verstanden habe) durch die Kombination von $id und $no eindeutig identifiziert. Daraus kannst Du dann den Namen bilden. Die verkleinerten Versionen der Bilder kannst Du dynamisch erzeugen, indem Du z.B. Skripte für folgende URL-Struktur machst:
          http://neoflo.ne.funpic.de/thumbnail.php?id=10&no=8
          http://neoflo.ne.funpic.de/image.php?id=10&no=8
          Die erste URL ruft die Miniaturansicht eines Bildes ab, die zweite die Originalgröße. Die beiden Skripte können die Bilder ggf. dynamisch erzeugen. Das zweite Skript kann aber auch einfach die entsprechende Datei zurückgeben. Dadurch hast Du eine einheitliche Benennung, und es kann keine Cachekonflikte mehr geben, da jedes Bild und jede Miniaturansicht ihre eigene URL hat. Die URLs lassen sich auch einfach in die skriptgenerierte HTML Seite integrieren, da Du $id und $no der Bilder immer kennst bzw. an die nächste Seite weitergibst.

          MfG
          GK

          Aber mache ich nicht genau das hier:

          href='showFoto.php?id=$id&no=$no_rueck'> <img             src='./img/prev.jpeg 'alt='vorheriges'             style='border-color: black'> </a> </li>";

          1. Aber mache ich nicht genau das

            Nein, machst Du nicht. Der Link auf showFoto.php?id=$id&no=$no_rueck liefert lediglich html-Text zurück. Innerhalb dieses Textes steht dann wieder ein img-Tag, welches auf eine vom Browser bereits geladene Bilddatei verweist. Diese wird dann natürlich nicht neu geladen. Mach Dir klar, wieviele Requests vom Client gestellt werden, wenn er eine HTML Datei aufbaut und welche Daten dabei geladen werden:
            1. Der Browser lädt die in der Adresse angegebene URL (z.B. http://neoflo.ne.funpic.de/showFoto.php?id=10&no=8). Daraus resultiert (meistens) HTML-Text. Dieser wird geparsed. Anschließend werden die Bilder geladen, die im HTML Quelltext gefunden werden.
            2. Für jedes Bild wird ein eigener Request generiert. (z.B. für http://neoflo.ne.funpic.de/image_neu.JPG) Sofern ein Bild schon geladen wurde und im Cache des Browsers steht, wird es nicht erneut geladen, ausser bei einer expliziten Aktualisierung. Dabei gilt, dass ein und dasselbe Bild natürlich auf mehreren Seiten vorhanden sein kann, was ja z.B. bei Hintergrundbildern auch üblich ist. Die URLs der Bilder ergeben sich aber aus dem Wert des src-Attributes des img-Tags der Seite in der sie enthalten sind. Für den Brower bezieht sich <img src='image_neu.JPG'> immer auf dasselbe Bild, auch wenn dieses Bild auf verschiedenen Seiten verwendet wird. Die URL der Seite auf der ein Bild verwendet wird ist unabhängig von der URL des Bildes selbst. Du musst also die URL, welche das Bild referiert ändern, z.B. indem das Bild durch ein Skript zurückgegeben wird. Dann steht in deinem HTML Text etwa <img src='thumbnail.php?id=10&no=8'> für die Miniaturansicht und <img src='image.php?id=10&no=8'> für die Originalgröße.

            Kurz gesagt: Der Browser denkt, Du verwendest das gleiche Bild auf mehreren Seiten und lädt dies nicht erneut. Sorge dafür, dass die Bilder (nicht die HTML-Seiten, auf denen sie verwendet werden) unterschiedliche URLs haben und die Sache funzt.

            MfG
            GK

            1. Also, wenn ich dich richtig verstehe, dann muss an diese Stelle:

              echo "<img src='image_neu.JPG' style='border: 2px solid #C20000'>";

              etwas wie

              echo "<img src='showFotoGross.php?id=$id&no=$no' style='border: 2px solid #C20000'>";

              Doch was muss dann in diese Datei? wie gebe ich dann dort das Bild aus oder zurück?
              Dieser Teil des Skripts verkleinert mir ja das Foto:

              $bild = $row[4].$no.".JPG";
              $size=getimagesize($bild);
              $newwidth = 700;
              $newheight = 525;
              $oldimage = ImageCreateFromJPEG($bild);
              $newimage = imagecreatetruecolor($newwidth, $newheight);
              ImageCopyResized($newimage, $oldimage, 0, 0, 0, 0, $newwidth, $newheight, $size[0], $size[1]);
              ImageJPEG($newimage, "image_neu.JPG");

              Aber das Foto würde dann ja wieder in einer Datei gespeichert und ich hätte wieder das Problem mit dem Browser Cache, das ich ja gerne vermeiden würde! :(

              1. Sofern Du PHP5 einsetzt, kannst Du folgenden Code verwenden. Das Beispiel liefert die Datei test.jpg in der Größe von 200 Pixeln zurück. Der Einsatz der gd-FUnktionen ist aber in anderen Versionen nicht anders.

                <?php
                  final class Image
                  {
                    private $m_Filename;
                    private $m_Handle;
                    private $m_ImageInfo;

                public function __construct($filename)
                    {
                      $this->m_Filename = $filename;
                      $this->m_Handle = null;
                      $this->m_ImageInfo = null;
                    }

                public function __destruct()
                    {
                      if (is_resource($this->m_Handle))
                        imagedestroy($this->m_Handle);
                    }

                public function __get($name)
                    {
                      switch ($name)
                      {
                        case "File":
                          $value = $this->m_Filename;
                          break;

                case "IsValid":
                          $value = (file_exists($this->m_Filename) && is_resource($this->__get("Handle")));
                          break;

                case "Width":
                          if (is_null($this->m_ImageInfo))
                            $this->m_ImageInfo = GetImageSize($this->m_Filename);
                          $value = (int)$this->m_ImageInfo[0];
                          break;

                case "Height":
                          if (is_null($this->m_ImageInfo))
                            $this->m_ImageInfo = GetImageSize($this->m_Filename);
                          $value = (int)$this->m_ImageInfo[1];
                          break;

                case "Handle":
                          if (is_null($this->m_Handle) && file_exists($this->m_Filename))
                          {
                            if (is_null($this->m_ImageInfo))
                              $this->m_ImageInfo = GetImageSize($this->m_Filename);
                            switch ($this->m_ImageInfo[2])
                            {
                              case 1:
                                $this->m_Handle = imagecreatefromgif($this->m_Filename);
                                break;

                case 2;
                                $this->m_Handle = imagecreatefromjpeg($this->m_Filename);
                                break;

                case 3:
                                $this->m_Handle = imagecreatefrompng($this->m_Filename);
                                break;

                default:
                                throw new Exception("Image::Handle - Cannot load image from {$this->m_Filename}");
                                break;
                            }
                          }
                          $value = $this->m_Handle;
                          break;

                default:
                          throw new Exception("Unknown property {$name}");
                          break;
                      }
                      return($value);
                    }

                public function Write()
                    {
                      $size = (0 < func_num_args()) ? func_get_arg(0) : null;
                      if (is_integer($size) && ($size < 100))
                        $size = 100;
                      $destroy = false;
                      $handle = $this->Handle;
                      if (is_integer($size) && ($size < max($this->Width, $this->Height)))
                      {
                        if ($this->Width < $this->Height)
                        {
                          $width = $this->Width * $size / $this->Height;
                          $height = $size;
                        }
                        else
                        {
                          $height = $this->Height * $size / $this->Width;
                          $width = $size;
                        }
                        $image = imagecreatetruecolor($width, $height);
                        imagecopyresampled($image, $handle, 0, 0, 0, 0, $width, $height, $this->Width, $this->Height);
                        $handle = $image;
                        $destroy = true;
                      }
                      header("Content-type: image/jpeg");
                      imagejpeg($handle);
                      if ($destroy)
                        imagedestroy($handle);
                    }
                  }

                $image = new Image("test.jpg");
                  $image->Write(200);
                ?>

                Auf Basis dieses Codes kannst Du zwei Skripte erstellen, z.B. thumbnail.php und image.php, die jeweils die Miniaturansicht und die große Ansicht zurückgeben. Den Dateiname kannst Du mit Hilfe von Get-Variablen (z.B. $_GET["id"] und $_GET["no"]) ermitteln. Der Vorteil dieser Vorgehensweise ist, dass auch die Miniaturansichten dynamisch generiert werden können. Nachteil ist natürlich, dass das den Server stärker belastet, da er die Bilder bei jedem Abruf errechnen muss. Dem kann aber durch einen Caching Mechanismus vorgebeugt werden (zu Lasten des Festplattenplatzes, mann kann halt nicht alles haben).

                Übrigens: Bei der Verarbeitung von URL-Parametern solltest Du auf jeden Fall ein Minimum an Parametervalidierung vornehmen, bevor Du diese in einer SQL-Anweisung verbaust. Andernfalls ist dein Code anfällig für SQL-Injection. Für deine URL Parameter würde ich wenigstens
                $id = (int)$_GET["id"];
                $no = (int)$_GET["no"];
                schreiben, damit in $id und $no auch wirklich nur Zahlen drin stehen.

                MfG
                GK

                1. Hallo,

                  erstmal sorry, dass ich mich erst jetzt melde! :)
                  Aber es war viel zu tun!

                  Ich habe mir jetzt folgendes Skript gebastelt:

                  showFotoKlein.php :
                  <?php
                   $id = $_GET['id'];
                   $no = $_GET['no'];
                   $bild = $_GET['bild'];

                  $size = getimagesize($bild);
                   $newwidth = 700;
                   $newheight = 525;
                   $oldimage = ImageCreateFromJPEG($bild);
                   $newimage = imagecreatetruecolor($newwidth, $newheight);
                   ImageCopyResized($newimage, $oldimage, 0, 0, 0, 0, $newwidth, $newheight, $size[0], $size[1]);

                  header('Content-type: image/jpeg');
                   header('Content-length: '.filesize($newimage));
                   imagejpeg($newimage);
                  ?>

                  Diese Datei wird in showFoto durch "echo "<img src='showFotoKlein.php?id=$id&no=$no&bild=$bild'>";" aufgerufen!
                  Doch es passiert einfach nichts! Es wird nichts angezeigt und ich bekomme auch keine Fehlermeldung!

                  Ich hoffe du liest die Antwort noch... :)

                  Mfg Florian

                  1. Die Content-length Zeile muss raus. $newimage ist eine php Resource, kein Dateiname und kann daher nicht Argument der filesize-Funktion sein. Zum Testen rufe
                    http://deine.domain/showFotoKlein.php?id=$id&no=$no&bild=$bild
                    auf, wobei für $id, $no und $bild natürlich geeignete Werte einzusetzen sind. Der Browser zeigt das Bild dann an, oder eben eine Fehlermeldung. Das Problem bei Seiten mit dynamisch erzeugten Bildern ist halt, dass man über einen Fehler beim Laden des Bildes nicht informiert wird. Also ruft man das Bild direkt ab, ohne eine Seite.
                    Wenn das Bild nicht angezeigt wird, kannst Du im Skript echo Ausgaben machen, um zu sehen, bis wohin er kommt und wie die Variablen gesetzt sind. So kann man z.B. Fehler wie einen falsch zusammengesetzten Dateinamen erkennen. Natürlich sollten dann die Zeilen
                    header('Content-type: image/jpeg');
                    imagejpeg($newimage);
                    auskommentiert werden. Auf diese Weise kannst Du sicherstellen, dass in $newimage auch wirklich ein gültiges Bild der entsprechenden Größe drin ist. Das kannst Du mit den gd Funktionen und is_resource feststellen. Wenn das so ist, kannst Du die Debugausgaben wieder entfernen und die beiden obigen Zeilen einkommentieren. Beachte, dass vor der Ausführung der header-Aufrufe KEINE AUSGABEN (garkeine, auch kein Leerzeichen, Zeilenumbruch oder sonst was) gemacht werden dürfen, sonst bekommst Du die Meldung "Headers already sent".
                    Falls das nicht funktioniert versuche es mit imagecopyresampled statt imagecopyresized. Du kannst auch erstmal das mit ImageCreateFromJPEG erstellte Bild ohne Skalierung ausgeben, um zu sehen ob es an der Größenänderung liegt, wenn's nicht funktioniert.
                    Falls es dann immer noch nicht geht bleibt dir als letzte Möglichkeit nur noch per Netzwerkmonitor die Pakete zu analysieren.

                    MfG
                    GK

          2. Nachtrag:
            Das von Dir verwendete Verfahren ist auch nicht praxistauglich, denn Du kommunizierst zwischen mehreren Anfragen über eine globale Datei namens image_neu.jpg. Wenn es nun mehrere gleichzeitige Zugriffe verschiedener Clients gibt, überschreiben spätere Anfragen die von vorherigen Anfragen erzeugte Datei und zwar auch dann, wenn der jeweilige Client diese noch nicht abgerufen hat. Die Seiten werden ja auf Basis von mehreren Anfragen zusammengesetzt, zwischen denen der Server auch noch Anforderungen von anderen Clients beantworten kann. Das Resultat wäre, dass falsche Bilder an den Client ausgeliefert würden, selbst dann wenn es kein Cachingproblem gäbe. Die verwendete Methode funktioniert nur bei seeeehr geringer Last, nämlich maximal einem Client.

            MfG
            GK

      2. Hi,

        für clientseitige Probleme ist serverseitiger Code nicht nur vollkommen irrelevant, sondern störend.
        Wo soll der Fehler sonst liegen, wenn nicht in dem Teil des Programms?

        in dem, was der Code erzeugt.

        Was die Sache mit dem Cache angeht:
        Das ist sicher eine Möglichkeit, aber wie kann ich das denn vermeiden?
        ich kann ja nicht jedesmal einen anderen Dateinamen für das Bild verwenden, weil ich das jeweilige Bild nur temporär verkleinern möchte!

        Du befindest Dich im HTTP-Umfeld. HTTP kennt keine Dateien, sondern nur Ressourcen; es kennt auch keine Dateinamen, sondern nur URIs. Sorge dafür, dass die Ressourcen mit verschiedenen URIs angefordert werden.

        Cheatah

        --
        X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
        X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
        X-Will-Answer-Email: No
        X-Please-Search-Archive-First: Absolutely Yes
  2. ... "vorwärts" geklickt habe, dann verweist der Pfad auf das nächste Bild, klicke ich nochmal, auf das übernächste etc. Wenn ich nun aber F5, also aktualisieren drücke, dann wird das Bild korrekt angezeigt?!

    echo "<img src='image_neu.JPG' style='border: 2px
                    solid #C20000'>";

    du nutzt für das Bild immer den selben Namen. könnte der Browser auch das Bild aus dem Cache nehmen ...

    Gruß planB