【问题标题】:Outputting image using php使用php输出图像
【发布时间】:2020-07-04 14:35:08
【问题描述】:

有一堆与这个标题相同的问题。 比如

答案总是有一些变化

header('Content-type: image/jpeg'); 添加到您的代码中

毫无疑问,这是答案的重要部分,但遗漏了一些我真的无法解决的重要步骤。

Now, there is obvious benefit to fetching an image using php when the image is situated below the root directory.

假设你有一个网页

<?php
require_once("load_a_scripts.php");
print("lots of html");

// fetch image from below root directory and output in HTML
?>
<img id="this_one" src="" height="200" width="200" />

你想输出this_one,上面的图像吗?

PHP 可用于使用 readfile() 来获取所需的文件,但这在这里不会非常有用(充其量你会得到随机的 unicode 输出而不是正确的图像)。

防止乱码输出的解决方法是使用

header('Content-type: image/jpeg');

这显然在这里似乎不合适。不仅有输出,这将使设置标题变得不可能,而且即使这个操作过程成功,最好的希望是图像的下载提示。同样,这不是所需的功能。

因此,一些解决方案建议使用一些外部代码,例如“image.php”,它将有自己的标头并获取图像,等等。但是,这又存在一些问题。

image.php 怎么知道你想要什么图片?

 <?php header('Content-Type:'.$photo);

 if(isset($photo)&&isset($type)){
     if(strlen($photo)>15||strlen($type)>6){
        die();
        }


    $photo = strtolower($photo);
    $photo = preg_replace('/[^a-z0-9 -]+/', '', $photo);
    $photo = str_replace(' ', '-', $photo);
    $photo = trim($photo, '-');
    $type = strtolower($type);
    $type = preg_replace('/[^a-z0-9 -]+/', '', $type);
    $type = str_replace(' ', '-', $type);
    $type = trim($type, '-');

    readfile('../img/'.$user_id.$photo);
}

与图像名称 ($photo) 和 mime ($type) 相关的参数假设可以使用 GET 发送,但同样,这些参数是由什么发送的,以及如何发送?

一些答案​​似乎表明您可以直接链接到外部 image.php,就好像它是图像一样

<img src="image.php" /> 

但这又提出了一个问题,即 image.php 如何知道 $photo 和 $type 的值。

【问题讨论】:

  • 为了搞清楚,您是在尝试基于 GET 变量动态加载 &lt;img ../&gt; 标记,还是希望基于 url 加载整个 php 脚本,例如 http://placehold.it/200x200
  • 请更准确简洁地描述您的问题。
  • @MatthewSpence 我想使用 php 动态加载图像。写
  • @KunalRaut 你有什么问题?这样的问题太多了,所以我担心会因为重复而被删除。

标签: php image http-headers


【解决方案1】:

您有两个基本选择:首先,使用外部图像加载器/处理程序脚本(例如&lt;img src="image.php?i=sunshine.jpg" /&gt;);其次,对图像数据进行base64编码(例如&lt;img src="data:image/png;base64, i26dfdXAd..." /&gt;)。第二个选项将使您的 HTML 膨胀,就像没有明天一样。那么让我们简单看一下image.php 处理程序的方法。

处理程序如何知道要显示什么图像?它需要一个查询字符串,例如image.php?i=sunshine.jpg;或image.php?i=sunshine&amp;x=jpg;或image.php?i=sunshine&amp;x=jpg&amp;s=600,如果您想加载特定尺寸,等等。您必须在 HTML 源代码中使用该格式,没有脚本可以自动知道要加载的图像。然后,发送参数的是“谁”(你),而不是“什么”。您需要确保变量已正确清理(正如您的示例处理程序所做的那样);像任何用户可修改的输入一样,它们不应该被信任,尤其是在文件系统操作(目录遍历等)附近的任何地方。这些变量将以$_GET['i']$_GET['x'] 等形式提供给您的处理程序脚本。

如果您觉得 URL 参数很麻烦,或者只是看起来很脏,您可以随时重写 URL。将图像链接为&lt;img src="images/sunshine.jpg" /&gt;,并在/images/ 文件夹(仅包含您的脚本)中设置.htaccess 重写规则,将所有图像请求传递给您的处理程序脚本。有关示例,请参阅"htaccess redirect all images to handler" Q/A。您还可以使用这种方法来处理缩小的图像版本,将 &lt;img src="images/sunshine__600.jpg" /&gt; 等源 URL 映射到重写规则。

关于使用readfile()(对内存最友好的大块数据脱口方式),只要在调用readfile() 之前输出header('Content-type: image/jpeg');(或其他适当的MIME 标头),它将以所需的方式工作。也就是说,浏览器不知道网络服务器直接从文件系统提供的图像与使用处理程序从 webroot 外部提供的图像之间的区别。它只是带有图像 HTTP 标头的数据。


编辑:奖金。编写了一个极简的可安全部署的文件处理程序。

<?php
/* 
 * Receive image call as: <img src="img.php?i=name.jpg" />
 * Output matching image file from $basepath directory
 */

$basepath = '../images/'; // Path to image folder

$mimes = [ // Allowed image types:
    'jpg' => 'image/jpeg',
    'png' => 'image/png',
    'gif' => 'image/gif',
    'svg' => 'image/svg+xml',
];

!isset($_GET['i']) && die(); // Nothing to do here.

// Parse & Verify Extension
$ext = strtolower(pathinfo($_GET['i'], PATHINFO_EXTENSION));
!isset($mimes[$ext]) && die('Invalid filetype!'); // If MIME N/A: die!

// Parse & Sanitize Filename 
$file = basename($_GET['i']);
$file = preg_replace('#[^[:alnum:] ._-]#', '', $file);

$filepath = realpath($basepath . $file);
$filepath === false && die('Invalid filename!'); // If image N/A: die!

// Output MIME header and image:
header('Content-Type:' . $mimes[$ext]);
readfile($filepath);
exit;

如果您需要适应 jpeg 等变体,只需 a) 在 $mimes 数组中复制 MIME 定义,或 b) 添加扩展规范化例程。如果您需要访问子文件夹中的图像,例如?i=sun/shine.jpg,在没有basename 的情况下重新编写文件名解析/清理例程。 (确保您远离directory traversal!)。 [:alnum:] ._-] 以外的字符将从请求的文件名中删除。根据需要修改正则表达式。

【讨论】:

  • 所以基本上它所需要的只是正确更改 src 属性?这听起来比我预期的要容易
  • 是的,没错。一个&lt;img&gt; 标记,带有指向处理程序的适当src 属性,以及一个提供图像的处理程序脚本。
  • 我添加了一个新的图像处理程序样本。似乎按预期工作。 ^_^
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-11
  • 1970-01-01
  • 2012-05-03
  • 2010-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多