返回一个PHP页面作为图像


69

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

我的index.php具有这样的图像链接:

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

和我的PHP脚本基本上做到这一点:

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

一旦弄清楚了,我将删除所有一起输入的文件名,并将其替换为图像ID。

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


1
只需添加一些安全性<img src='test.php?image=../config.php' />即可避免类似的攻击
mixdev

Answers:


119

PHP手册包含以下示例

<?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标头。另外,您必须注意不要在<?php ... ?>标签之前或之后在文件中包含任何多余的空格(例如换行符)。

如注释中所建议,可以通过省略?>标签来避免脚本末尾出现多余空格的危险:

<?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无签名”(Emacs)或类似名称。


14
为此,有些人(包括Zend,PEAR或两者-我忘了)建议省略结尾处的?>。从语法上讲,它是完全有效的,并且保证结尾空格不会出现任何问题。
Frank Farmer

12
但是,但是...很奇怪没有关闭一个开放的:-)
Martin Geisler

2
不要忽略?>。“更简单”并不意味着“更好”。
贾里德·法瑞什

3
完全同意弗兰克·法默(Frank Farmer)的观点,没有结尾的代码>将会更易于调试。这只是一个非常有用的提示。回答贾里德·法瑞什(Jared Farrish),这里的简单意味着更好,这是正确的,并且应该在任何地方使用,因为您的代码不应被错误检查或其他任何内容(如果您不输入它,则它会在出现某些错误时给您带来广告) 。它节省了很多调试时间。
鲍里斯·格里(BorisGuéry),2009年

2
我只是认为“关闭标签”是一种更好的做法。我没有任何花哨的答案,但这是两个字母,从语义上来说,我认为它比较完整。那只是我的意见。:)
贾里德·法瑞什

29

我觉得我们可以通过仅从$ 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所做的贡献。


1
fpassthru文档页说:“如果你只想转储文件的输出缓冲区的内容,如果不先修改,或寻求特定抵消,您可能需要使用ReadFile的(),从而节省您的fopen()调用。” 这样做readfilefpassthru在这种情况下更有效更好。
爱德华

2
header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");如果文件不存在,并且需要在响应中对此进行通知,则可以使用该代码。
爱德华

1
该变量$fileOut应包含文件名: $fileOut = "your_file_name.png";
metatron '17

@Edward和Metatron,感谢您的回复。我现在已经相应地更新了我的答案和代码。
禁止地球工程'18

1
@ ban-geoengineering-不,我不知道,而且网上似乎没有可行的替代方案(或者,如果有,谷歌找不到它们……)。请注意,这不是“投诉”,只是一条便条-尽管这些天我猜想大多数PHP安装都将内置GD,但有些却没有,因此请注意。
Gwyneth Llewelyn


4

我没有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;

-5

如果您不从数据库中读取数据,另一个简单的选择(没有更好,只是有所不同)是仅使用一个函数为您输出所有代码...注意:如果您还希望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,[...]"
3ED
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.