在 PHP 中输​​出图像

Posted

技术标签:

【中文标题】在 PHP 中输​​出图像【英文标题】:Output an Image in PHP 【发布时间】:2010-12-23 12:53:58 【问题描述】:

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

mime 类型为$type

如何输出到浏览器?

【问题讨论】:

到目前为止你尝试过什么?使用<img> 标签有什么问题吗? 【参考方案1】:
header("Content-type: image/png"); 
echo file_get_contents(".../image.png");

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

【讨论】:

您好,欢迎来到 Stack Overflow!您介意更新您的答案并解释您的解决方案为何有效吗?您是否还可以从答案周围删除引号,因为这会使语法突出显示将其全部视为字符串文字。谢谢! 请分享一些解释。比如为什么要设置Content-type: image/png输出一张JPG图片?另外,为什么将整个文件读入一个变量? readfile不应该有更好的内存性能吗?【参考方案2】:

(在accepted answer...上展开)

我需要:

    日志查看 jpg 图像 动画gif和, 确保图像从不缓存(因此每个视图都会被记录),并且,保留原始文件扩展名

我通过在图像所在的子文件夹中创建一个“辅助”.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);
?>

图像可以正常渲染(或动画),并且可以通过图像的任何正常方式调用(如&lt;img&gt; 标签),并将保存访问 IP 的记录,同时对用户不可见。

【讨论】:

【参考方案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)”部分。谢谢!【参考方案4】:
    $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" 之后,我得到了味道,并且可以工作! 这是屏幕截图: Screenshot of "secure image" from database

【讨论】:

【参考方案5】:

您可以使用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 会为您完成。

【讨论】:

【参考方案6】:
$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 getimagesize() 函数将确定任何给定图像文件的大小并返回尺寸以及文件类型和要在其中使用的高度/宽度文本字符串一个普通的 html IMG 标签和对应的 HTTP 内容类型。【参考方案7】:

如果您可以自己配置网络服务器,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 文件,你肯定会遇到问题。

【讨论】:

有趣的评论关于文件大小和由于阅读它而导致的潜在内存问题【参考方案8】:

试试这个:

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

【讨论】:

【参考方案9】:

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

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

readfile输出图片内容:

readfile($file);

也许(可能没有必要,但是,以防万一)您也必须发送 Content-Length 标头:

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

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

【讨论】:

【参考方案10】:
header('Content-type: image/jpeg');
readfile($image);

【讨论】:

【参考方案11】:
$file = '../image.jpg';
$type = 'image/jpeg';
header('Content-Type:'.$type);
header('Content-Length: ' . filesize($file));
readfile($file);

【讨论】:

PHP 和/或服务器将为您处理内容长度。 方便起见的内容长度标头。 由于某种原因,当我尝试通过绝对路径访问图像时文件大小失败,所以我评论了该行并且代码工作正常。 最好避免使用 Content-Length ,尤其是在您的网络服务器上启用了 GZip 的情况下,因为您会告诉浏览器期望的字节数比实际到达的字节数多,它会等待超时。这可能会产生不良后果,例如你有 JS 等待事件。 确保“Content-Type”中的类型大写。我刚刚遇到了“内容类型”,结果是一堆乱码【参考方案12】:
<?php

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

这是简短的版本。你可以做一些额外的小事来让事情变得更好,但这对你有用。

【讨论】:

以上是关于在 PHP 中输​​出图像的主要内容,如果未能解决你的问题,请参考以下文章

SQL fetch 数组中的弹出图像显示相同的图像

如何用ENVI和ARCGIS切割出图像的制定区域

Gridview - 单击时在另一个框中弹出图像

PHP Javascript - 弹出图像redimensionado desde padre。

xamarin表单 - 使用c#计算出图像源的尺寸

利用OpenCV的函数calcHist()计算出图像的直方图数据后绘制图像的直方图