用PHP输出图像


70

我有一张图片$file(例如../image.jpg

有一个哑剧类型 $type

如何将其输出到浏览器?


你试过什么了?使用<img>标签有什么问题吗?
Nico Haase

Answers:


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

16
PHP和/或服务器将为您处理内容长度。
马修·沙利

1
内容长度标头,以方便使用。
Emre Yazici,2009年

2
由于某些原因,当尝试通过绝对路径访问图像时,文件大小对我而言失败,因此我注释了该行,并且代码运行正常。
kiranvj 2013年

15
最好避免设置Content-Length,尤其是如果您在Web服务器上启用了GZip,因为您将告诉浏览器期望的字节数超过实际到达的字节数,并且它将等待超时。如果例如您有JS等待事件,则可能会带来严重后果。
编码器

确保“内容类型”中的类型为大写。我只是遇到了“内容类型”问题,这导致了一堆乱码
-AllisonC

32

如果您可以自由配置自己的Web服务器,则mod_xsendfile(适用于Apache)之类的工具比用PHP读取和打印文件要好得多。您的PHP代码如下所示:

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

mod_xsendfile获取X-Sendfile标头,并将文件发送到浏览器本身。这可以对性能产生真正的影响,尤其是对于大文件。大多数提议的解决方案都将整个文件读入内存,然后将其打印出来。对于20kbyte的图像文件来说可以,但是如果您有200 MB的TIFF文件,那么肯定会遇到问题。


关于文件大小和由于读取全部而引起的潜在内存问题的有趣评论
伊恩

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/zh/function.fpassthru.php


@Michael via php.net getimagesize()函数将确定任何给定图像文件的大小,并返回尺寸以及要在常规HTML IMG标签和相应的HTTP内容中使用的文件类型和高度/宽度文本字符串。类型。
ReynekeVosz '16



3

对于遇到这个问题的下一个家伙,这对我有用:

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

您只需要所有这些。如果您的mimetype有所不同,请查看PHP的mime_content_type($ filepath)


支持“ mime_content_type($ filepath)”部分。谢谢!
coderama

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

这对我有用!我已经在代码点火器上对其进行了测试。如果我使用readfile,则图像不会显示。有时仅显示jpg,有时仅显示大文件。但是在我将其更改为“ file_get_contents”之后,我得到了味道,并且可以正常工作!这是屏幕截图:数据库中“安全图像”的屏幕 截图


1

(扩展接受的答案...)

我需要:

  1. 日志观看一个的jpg图像一个动画gif并且,
  2. 确保永不缓存图像(因此将记录每个视图),并且,
  3. 保留原来的文件扩展名

我通过在图像所在的子文件夹中创建一个“辅助”.htaccess文件来完成此操作。
该文件仅包含一行:

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

在同一文件夹中,我放置了两个“原始”图像文件(我们将它们称为orig.jpgorig.gif),以及下面的[simplified]脚本的两个变体(另存为myimage.jpgmyimage.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);
?>

图像可以正常渲染(或设置动画),并且可以通过图像的任何常规方式调用(如<img>标签),并且将保存访问IP的记录,而用户看不见。



0

您可以使用标头发送正确的Content-type:

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

readfile输出图像的内容:

readfile($file);


也许(也许不是必需的,但以防万一),您也必须发送Content-Length标头:

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


注意:请确保除了图像数据(例如没有空格)之外,不要输出任何其他内容,否则它将不再是有效的图像。


0

您可以使用finfo(PHP 5.3+)获得正确的MIME类型。

$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:您不必指定Content-Length,Apache会为您完成。


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

第一步是从特定位置检索图像,然后将其存储到为此目的的变量中,我们将函数file_get_contents()与目标作为参数。接下来,我们使用头文件将输出页面的内容类型设置为图像类型。最后,我们使用echo打印检索到的文件。


4
您好,欢迎来到Stack Overflow!您介意对您的解决方案起作用的一些解释来更新您的答案吗?您是否还可以从答案中删除引号,因为这使语法突出显示部分将其全部视为字符串文字。谢谢!
Michael Cordingley

请分享一些解释。例如,为什么要设置Content-type: image/png输出JPG图像?另外,为什么将整个文件读入变量?难道不应该readfile有更好的内存性能吗?
Nico Haase
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.