Felix Riesterer: imagepng und Content-Length

Beitrag lesen

problematische Seite

Lieber pl,

   imagepng($im);
   imagedestroy($im);
   header("Content-Type: image/png");

wenn man den Output-Buffer aktiv nutzt, dann kann man header()-Aufrufe egal wo machen, aber ob man unbedingt diese Infrastruktur nutzen will, ist eine Frage des Standpunktes. Anfangs habe ich das auch benutzt, aber mittlerweile schreibe ich meine PHP-Scripte so, dass sie das nicht mehr benötigen.

Wie in PHP so üblich, landet die Binary im Out Buffer und um die Ausgabe samt HTTP-Header kümmert sich PHP.

Das kann man so machen, muss man aber nicht. Will man die Daten zuerst in anderer Weise handhaben, kann man sie auch in eine Datei schreiben lassen. Dazu ist der zweite Parameter bei imagepng($res, $to), der dann ungleich nullsein muss.

Leider fehlt der Header Content-Length, wie bringe ich PHP dazu einen Solchen anzuhängen?

Wenn Du mit dem Output-Buffer hantierst, dann würde ich das so tun:

ob_start();

// stand schon etwas im Puffer?
$buffer_data = ob_get_clean();

// hier findet die Erzeugung Deines Bildes statt...

// Bilddaten in den Puffer schreiben
imagedestroy($im);

// Bilddaten aus dem Puffer holen
$img_data = ob_get_contents();

// Bild senden
header('Content-Type: image/png');
header('Content-Length: '.strlen($img_data));

// Puffer senden und Script hart beenden
ob_end_flush();
exit;

Wenn Dein Script vernünftig aufgebaut ist, kannst Du Dir den Teil mit ob_end_flush() und exit sparen. Auch wäre es eine Idee, eine temporäre Datei anzulegen, in die Du die Bilddaten schreiben lässt, um sie am Ende mit readfile() an den Browser ausgeben zu lassen. Damit wäre die ganze Puffer-Hantiererei nicht nötig und Dein Script könnte im Anschluss weiterlaufen, um z.B. noch diverse andere Dinge (z.B. logging) zu leisten:

function send_png_image ($im) {

  // temporäre Datei erzeugen
  $tmp = tmpfile();
  $path = stream_get_meta_data($tmp)['uri'];

  // Bilddaten in temporäre Datei schreiben
  imagepng($im, $tmp);
  imagedestroy($im); // EDIT

  // Bild senden
  header('Content-Type: image/png');
  header('Content-Length: '.filesize($path));

  readfile($path);
}

Liebe Grüße

Felix Riesterer