1 回答
TA贡献1783条经验 获得超4个赞
您有两个基本选项:首先,使用外部图像加载器/处理程序脚本(例如<img src="image.php?i=sunshine.jpg" />
);其次,对图像数据进行 base64 编码(例如<img src="data:image/png;base64, i26dfdXAd..." />
)。第二个选项会让你的 HTML 变得臃肿,就像没有明天一样。那么让我们简单地看一下image.php
处理程序方法。
处理程序如何知道要显示什么图像?它需要一个查询字符串,例如image.php?i=sunshine.jpg
;或image.php?i=sunshine&x=jpg
;或者image.php?i=sunshine&x=jpg&s=600
,如果您想加载特定尺寸,等等。您必须在 HTML 源中使用该格式,没有脚本可以自动知道要加载什么图像。然后,发送参数的是“谁”(您),而不是“什么”。您需要确保变量得到正确的清理(正如您的示例处理程序所做的那样);与任何用户可修改的输入一样,它们不应该被信任,尤其是靠近文件系统操作(目录遍历等)的任何地方。$_GET['i']
这些变量将作为、等供您的处理程序脚本使用$_GET['x']
。
如果您觉得 URL 参数很麻烦,或者看起来很脏,您可以随时重写 URL。将图像链接为<img src="images/sunshine.jpg" />
,并.htaccess
在 /images/ 文件夹(仅包含您的脚本)中设置重写规则,将所有图像请求传递到处理程序脚本。您还可以使用此方法来处理缩小的图像版本,并将源 URL<img src="images/sunshine__600.jpg" />
映射到重写规则。
关于使用readfile()
(脱口而出大块数据的最内存友好的方式),只要您在调用header('Content-type: image/jpeg');
之前输出(或其他适当的 MIME 标头)readfile()
,它就会以所需的方式工作。也就是说,浏览器不会知道网络服务器直接从文件系统提供的图像与通过处理程序从网络根外部提供的图像之间的区别。它只是带有图像 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) 复制数组中的 MIME 定义$mimes
,或 b) 添加扩展规范化例程。如果您需要访问子文件夹中的图像,例如?i=sun/shine.jpg
,请重新编写不带basename
. (确保您不会受到目录遍历的影响!)。[:alnum:] ._-]
将从请求的文件名中删除除 以外的字符。根据需要修改正则表达式。
- 1 回答
- 0 关注
- 160 浏览
添加回答
举报