【问题标题】:Return a PHP page as an image将 PHP 页面作为图像返回
【发布时间】:2010-10-28 08:44:24
【问题描述】:

我正在尝试读取图像文件(确切地说是 .jpeg),并将其“回显”回页面输出,但显示的是图像...

我的 index.php 有一个像这样的图片链接:

<img src='test.php?image=1234.jpeg' />

我的 php 脚本基本上是这样做的:

1) 读取 1234.jpeg 2) 回显文件内容... 3) 我觉得我需要用 mime 类型返回输出,但这就是我迷路的地方

一旦我弄清楚这一点,我将一起删除文件名输入并用图像 ID 替换它。

如果我不清楚,或者您需要更多信息,请回复。

【问题讨论】:

  • 只需添加一些安全措施,就可以避免像&lt;img src='test.php?image=../config.php' /&gt; 这样的攻击

标签: php image-processing http-headers mime-types


【解决方案1】:

PHP 手册有this example:

<?php
// open the file in a binary mode
$name = './img/ok.png';
$fp = fopen($name, 'rb');

// send the right headers
header("Content-Type: image/png");
header("Content-Length: " . filesize($name));

// dump the picture and stop the script
fpassthru($fp);
exit;
?>

重要的一点是您必须发送一个 Content-Type 标头。此外,您必须注意不要在文件中的 &lt;?php ... ?&gt; 标记之前或之后包含任何额外的空格(如换行符)。

根据 cmets 的建议,您可以通过省略 ?&gt; 标记来避免脚本末尾出现多余空白的危险:

<?php
$name = './img/ok.png';
$fp = fopen($name, 'rb');

header("Content-Type: image/png");
header("Content-Length: " . filesize($name));

fpassthru($fp);

您仍然需要小心避免脚本顶部的空白。一种特别棘手的空白形式是UTF-8 BOM。为避免这种情况,请确保将您的脚本保存为“ANSI”(记事本)或“ASCII”或“UTF-8 without signature”(Emacs)或类似文件。

【讨论】:

  • 为此,一些(包括 Zend、PEAR 或两者——我忘了​​)建议省略结束符?>。它在语法上完全有效,并且保证没有尾随空格的问题。
  • 但是,但是……不关闭打开的东西很奇怪:-)
  • 不要省略 ?>。 “更简单”并不意味着“更好”。
  • 完全同意 Frank Farmer 的观点,没有结尾的代码 ?> 会更容易调试。这只是一个非常有用的提示。并且回答 Jared Farrish,这里更简单确实意味着更好,这是正确的,它应该在任何地方使用,因为你的代码不应该被错误或任何东西,如果你不放它,如果有一些错误它会通知你.它节省了大量的调试时间。
  • 同意,省略结尾?&gt;。 @贾里德法瑞什;为什么你认为最好不要这样做?
【解决方案2】:

如果您不从数据库中读取数据,另一个简单的选项(不是更好,只是不同)是只使用一个函数为您输出所有代码... 注意:如果您还希望 php 读取图像尺寸并将其提供给客户端以加快渲染速度,您也可以使用此方法轻松实现。

<?php
  Function insertImage( $fileName ) {
    echo '<img src="path/to/your/images/',$fileName,'">';    
  }
?>

<html>
  <body>
    This is my awesome website.<br>
    <?php insertImage( '1234.jpg' ); ?><br>
    Like my nice picture above?
  </body>
</html>

【讨论】:

  • 这个“答案”会起作用,但 不能解决这个页面的上述问题。答案应始终回答原始问题。
  • 恕我直言,如果你想隐藏图片的位置,请将 base64 加密源放入 img 标签。 但这不是他问的。 src="data:image/png;base64,[...]"
【解决方案3】:

这应该可行。可能会慢一些。

$img = imagecreatefromjpeg($filename);
header("Content-Type: image/jpg");
imagejpeg($img);
imagedestroy($img);

【讨论】:

  • 这需要 PHP 已编译 GD。
【解决方案4】:

我觉得我们可以通过从 $image_info 获取 mime 类型来简化这段代码:

$file_out = "myDirectory/myImage.gif"; // The image to return

if (file_exists($file_out)) {

   $image_info = getimagesize($file_out);

   //Set the content-type header as appropriate
   header('Content-Type: ' . $image_info['mime']);

   //Set the content-length header
   header('Content-Length: ' . filesize($file_out));

   //Write the image bytes to the client
   readfile($file_out);
}
else { // Image file not found

    header($_SERVER["SERVER_PROTOCOL"] . " 404 Not Found");

}

使用此解决方案可以处理任何类型的图像,但这只是另一种选择。感谢 ban-geoengineering 的贡献。

【讨论】:

  • fpassthru 文档页面说“如果您只想将文件的内容转储到输出缓冲区,而不先修改它或寻找特定的偏移量,您可能想要使用 readfile (),从而为您节省了 fopen() 调用。”所以readfilefpassthru 更好,因为在这种情况下它更有效。
  • 如果文件不存在并且需要在响应中通知这一点,则可以使用代码header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");
  • 变量$fileOut应包含文件名:$fileOut = "your_file_name.png";
  • @Edward 和 metatron,感谢您的回复。我现在已经相应地更新了我的答案和代码。
  • @ban-geoengineering — 不,我没有,而且似乎网络上没有可行的替代方案(或者,如果有的话,谷歌找不到它们...... .)。请注意,这不是一个“投诉”,只是一个注释——尽管这些天我猜大多数 PHP 安装将内置 GD,有些不会,因此我的注释。
【解决方案5】:

我在没有 Content-Length 的情况下工作。可能是远程图像文件的原因

// open the file in a binary mode
$name = 'https://www.example.com/image_file.jpg';
$fp = fopen($name, 'rb');

// send the right headers
header('Cache-Control: no-cache, no-store, max-age=0, must-revalidate');
header('Expires: January 01, 2013'); // Date in the past
header('Pragma: no-cache');
header("Content-Type: image/jpg");
/* header("Content-Length: " . filesize($name)); */

// dump the picture and stop the script
fpassthru($fp);
exit;

【讨论】:

    【解决方案6】:

    非常非常容易。

    <?php
    
    //could be image/jpeg or image/gif or whatever
    header('Content-Type: image/png')
    readfile('image.png')
    ?>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-02
      • 1970-01-01
      • 1970-01-01
      • 2013-07-27
      • 2015-12-20
      • 1970-01-01
      • 2011-04-01
      • 1970-01-01
      相关资源
      最近更新 更多