Geben Sie ein Bild in PHP aus


70

Ich habe ein Bild $file(zB ../image.jpg)

das hat einen Pantomime-Typ $type

Wie kann ich es an den Browser ausgeben?


Was hast du bisher versucht? Ist etwas falsch an der Verwendung eines <img>Tags?
Nico Haase

Antworten:


139
$file = '../image.jpg';
$type = 'image/jpeg';
header('Content-Type:'.$type);
header('Content-Length: ' . filesize($file));
readfile($file);

16
PHP und / oder der Server kümmern sich für Sie um die Länge des Inhalts.
Matthew Scharley

1
Der Inhaltslängen-Header dient zur Vereinfachung.
Emre Yazici

2
Aus irgendeinem Grund ist die Dateigröße für mich fehlgeschlagen, als ich versucht habe, über einen absoluten Pfad auf das Bild zuzugreifen. Daher habe ich diese Zeile kommentiert und der Code funktioniert einwandfrei.
Kiranvj

15
Es ist besser, Content-Length nicht zu verwenden, insbesondere wenn Sie GZip auf Ihrem Webserver aktiviert haben, da Sie dem Browser mitteilen, dass er mehr Bytes erwarten soll, als tatsächlich eintreffen, und das Warten auf eine Zeitüberschreitung abwartet. Dies kann schlimme Folgen haben, wenn z. B. JS auf das Ereignis wartet.
Coder

Stellen Sie sicher, dass "Content-Type" groß geschrieben ist. Ich bin gerade darauf
gestoßen,

32

Wenn Sie die Freiheit haben, Ihren Webserver selbst zu konfigurieren, sind Tools wie mod_xsendfile (für Apache) erheblich besser als das Lesen und Drucken der Datei in PHP. Ihr PHP-Code würde folgendermaßen aussehen:

header("Content-type: $type");
header("X-Sendfile: $file"); # make sure $file is the full path, not relative
exit();

mod_xsendfile nimmt den X-Sendfile-Header auf und sendet die Datei an den Browser selbst. Dies kann einen echten Leistungsunterschied bewirken, insbesondere bei großen Dateien. Die meisten der vorgeschlagenen Lösungen lesen die gesamte Datei in den Speicher und drucken sie dann aus. Das ist für eine 20-KByte-Bilddatei in Ordnung, aber wenn Sie eine 200-MByte-TIFF-Datei haben, treten Probleme auf.


interessanter Kommentar über Dateigröße und mögliche Speicherprobleme aufgrund des Lesens in
Ian

26
$file = '../image.jpg';

if (file_exists($file))
{
    $size = getimagesize($file);

    $fp = fopen($file, 'rb');

    if ($size and $fp)
    {
        // Optional never cache
    //  header('Cache-Control: no-cache, no-store, max-age=0, must-revalidate');
    //  header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
    //  header('Pragma: no-cache');

        // Optional cache if not changed
    //  header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($file)).' GMT');

        // Optional send not modified
    //  if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) and 
    //      filemtime($file) == strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']))
    //  {
    //      header('HTTP/1.1 304 Not Modified');
    //  }

        header('Content-Type: '.$size['mime']);
        header('Content-Length: '.filesize($file));

        fpassthru($fp);

        exit;
    }
}

http://php.net/manual/en/function.fpassthru.php


@Michael via php.net Die Funktion getimagesize () bestimmt die Größe einer bestimmten Bilddatei und gibt die Abmessungen zusammen mit dem Dateityp und einer Textzeichenfolge für Höhe / Breite zurück, die in einem normalen HTML-IMG-Tag und dem entsprechenden HTTP-Inhalt verwendet werden sollen Art.
ReynekeVosz

4

Versuche dies:

<?php
  header("Content-type: image/jpeg");
  readfile("/path/to/image.jpg");
  exit(0);
?>


3

Für den nächsten Mann oder die nächste Frau, die dieses Problem hat, hat Folgendes für mich funktioniert:

ob_start();
header('Content-Type: '.$mimetype);
ob_end_clean();
$fp = fopen($fullyQualifiedFilepath, 'rb');
fpassthru($fp);
exit;

Sie brauchen das alles und nur das. Wenn Ihr Mimetyp variiert, schauen Sie sich PHPs mime_content_type ($ filepath) an.


Upvote für den Teil "mime_content_type ($ filepath)". Vielen Dank!
Coderama

1
    $file = '../image.jpg';
    $type = 'image/jpeg';
    header('Content-Type:'.$type);
    header('Content-Length: ' . filesize($file));
    $img = file_get_contents($file);
    echo $img;

Das funktioniert bei mir! Ich habe es auf Code Igniter getestet. Wenn ich Readfile verwende, wird das Bild nicht angezeigt. Manchmal nur JPG anzeigen, manchmal nur große Datei. Aber nachdem ich es in "file_get_contents" geändert habe, bekomme ich den Geschmack und funktioniert !! Dies ist der Screenshoot: Screenshot des "sicheren Bildes" aus der Datenbank


1

(Erweiterung der akzeptierten Antwort ...)

Ich musste:

  1. Protokollansichten eines jpgBildes und ein animiertesgif , und,
  2. Stellen Sie sicher, dass die Bilder niemals zwischengespeichert werden (damit jede Ansicht protokolliert wird) .
  3. auch behalten die ursprünglichen Dateierweiterungen .

Ich habe dies erreicht, indem ich eine "sekundäre" .htaccessDatei in dem Unterordner erstellt habe, in dem sich die Bilder befinden.
Die Datei enthält nur eine Zeile:

AddHandler application/x-httpd-lsphp .jpg .jpeg .gif

Im selben Ordner habe ich die beiden 'Original'-Bilddateien (wir nennen sie orig.jpgund orig.gif) sowie zwei Variationen des [vereinfachten] Skripts unten gespeichert (gespeichert als myimage.jpgund myimage.gif) ...

<?php 
  error_reporting(0); //hide errors (displaying one would break the image)

  //get user IP and the pseudo-image's URL
  if(isset($_SERVER['REMOTE_ADDR'])) {$ip =$_SERVER['REMOTE_ADDR'];}else{$ip= '(unknown)';}
  if(isset($_SERVER['REQUEST_URI'])) {$url=$_SERVER['REQUEST_URI'];}else{$url='(unknown)';}

  //log the visit
  require_once('connect.php');            //file with db connection info
  $conn = new mysqli($servername, $username, $password, $dbname);
  if (!$conn->connect_error) {         //if connected then save mySQL record
   $conn->query("INSERT INTO imageclicks (image, ip) VALUES ('$url', '$ip');");
     $conn->close();  //(datetime is auto-added to table with default of 'now')
  } 

  //display the image
  $imgfile='orig.jpg';                             // or 'orig.gif'
  header('Content-Type: image/jpeg');              // or 'image/gif'
  header('Content-Length: '.filesize($imgfile));
  header('Cache-Control: no-cache');
  readfile($imgfile);
?>

Die Bilder werden normal gerendert (oder animiert) und können auf eine der normalen Arten für Bilder (wie ein <img>Tag) aufgerufen werden. Sie speichern eine Aufzeichnung der besuchenden IP, während sie für den Benutzer unsichtbar sind.


0
<?php

header("Content-Type: $type");
readfile($file);

Das ist die Kurzversion. Es gibt ein paar zusätzliche kleine Dinge, die Sie tun können, um die Dinge schöner zu machen, aber das wird für Sie funktionieren.


0

Sie können den Header verwenden , um den richtigen Inhaltstyp zu senden:

header('Content-Type: ' . $type);

Und readfileum den Inhalt des Bildes auszugeben:

readfile($file);


Und vielleicht (wahrscheinlich nicht notwendig, aber nur für den Fall) müssen Sie auch den Content-Length-Header senden:

header('Content-Length: ' . filesize($file));


Hinweis: Stellen Sie sicher, dass Sie nichts anderes als Ihre Bilddaten ausgeben (z. B. kein Leerraum) , da dies sonst kein gültiges Bild mehr ist.


0

Sie können finfo(PHP 5.3+) verwenden, um den richtigen MIME-Typ zu erhalten.

$filePath = 'YOUR_FILE.XYZ';
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$contentType = finfo_file($finfo, $filePath);
finfo_close($finfo);

header('Content-Type: ' . $contentType);
readfile($filePath);

PS : Sie müssen nicht angeben Content-Length, Apache wird es für Sie tun.


-1
header("Content-type: image/png"); 
echo file_get_contents(".../image.png");

Der erste Schritt besteht darin, das Bild von einem bestimmten Ort abzurufen und es dann in einer Variablen zu speichern. Zu diesem Zweck verwenden wir die Funktion file_get_contents () mit dem Ziel als Parameter. Als nächstes legen wir den Inhaltstyp der Ausgabeseite mithilfe der Header-Datei als Bildtyp fest. Schließlich drucken wir die abgerufene Datei mit Echo.


4
Hallo und willkommen bei Stack Overflow! Würde es Ihnen etwas ausmachen, Ihre Antwort mit einer Erklärung zu aktualisieren, warum Ihre Lösung funktioniert? Könnten Sie auch die Anführungszeichen aus Ihrer Antwort entfernen, da der Syntax-Textmarker dadurch alles als Zeichenfolgenliteral behandelt? Vielen Dank!
Michael Cordingley

Bitte teilen Sie einige Erklärungen. Warum haben Sie beispielsweise die Content-type: image/pngAusgabe eines JPG-Bildes festgelegt? Warum sollte die gesamte Datei in eine Variable eingelesen werden? Sollte nicht readfileeine viel bessere Speicherleistung haben?
Nico Haase
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.