Chr*_*wes 14 php caching resize image
使用PHP处理图像缓存的最佳实践方法是什么?
文件名当前存储在MySQL数据库中,该数据库在上载时重命名为GUID,以及原始文件名和alt标记.
当图像被放入HTML页面时,使用诸如'/images/get/200x200/{guid}.jpg之类的URL完成,该URL被重写为php脚本.这允许我的设计者指定(粗略地 - 源图像可能更小)文件大小.
然后php脚本创建一个大小(url中为200x200)和GUID文件名的散列,如果之前生成了文件(TMP目录中存在散列名称的文件),则从应用程序TMP目录发送该文件.如果散列文件名不存在,则创建它,写入磁盘并以相同方式提供,
这有效吗?(它还支持对图像加水印,并且水印设置也存储在哈希中,但这超出了范围.)
Dan*_*dey 30
我会以不同的方式做到这一点.
问题:1.让PHP提供文件的效率低于可能的效率.2.每次请求图像时,PHP都必须检查文件是否存在.3.Apache在这方面要比PHP好得多.
这里有一些解决方案.
你可以mod_rewrite在Apache上使用.可以使用mod_rewrite来测试文件是否存在,如果存在,则改为提供该文件.这完全绕过了PHP,使事情变得更快.但是,实现此目的的真正方法是生成应始终存在的特定URL模式,然后再重定向到PHP.
例如:
RewriteCond %{REQUEST_URI} ^/images/cached/
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteRule (.*) /images/generate.php?$1 [L]
Run Code Online (Sandbox Code Playgroud)
因此,如果客户端请求/images/cached/<something>并且该文件尚不存在,Apache将重定向请求/images/generate.php?/images/cached/<something>.然后,此脚本可以生成映像,将其写入缓存,然后将其发送到客户端.将来,除了新图像之外,永远不会调用PHP脚本.
使用缓存.正如另一张海报所说,使用mod_expiresLast-Modified标头等来响应条件GET请求.如果客户端不必重新请求图像,则页面加载将显着加快,并且服务器上的加载将减少.
对于必须从PHP发送映像的情况,您可以使用mod_xsendfile更少的开销来完成它.请参阅Arnold Daniels关于此问题的优秀博客文章,但请注意他的示例是下载.要内联提供图像,请取出Content-Disposition标头(第三个header()调用).
希望这有助于 - 在我的偏头痛清除后更多.
小智 10
Dan Udey的重写示例中有两个拼写错误(我无法评论),它应该是:
RewriteCond %{REQUEST_URI} ^/images/cached/
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteRule (.*) /images/generate.php?$1 [L]
Run Code Online (Sandbox Code Playgroud)
问候.
值得添加的一个注意事项是确保您的代码不会生成这些图像的"未授权"大小.
因此,如果尚不存在,则以下URL将创建200x200版本的图像1234.我强烈建议您确保所请求的网址包含您支持的图片尺寸.
/images/get/200x200/1234.jpg
Run Code Online (Sandbox Code Playgroud)
恶意的人可以开始请求随机URL,总是改变图像的高度和宽度.这会导致您的服务器出现一些严重的问题b/c它将坐在那里,基本上受到攻击,生成您不支持的大小的图像.
/images/get/0x1/1234.jpg
/images/get/0x2/1234.jpg
...
/images/get/0x9999999/1234.jpg
/images/get/1x1/1234.jpg
...
etc
Run Code Online (Sandbox Code Playgroud)
这是一段随机的代码片段,说明了这一点:
<?php
$pathOnDisk = getImageDiskPath($_SERVER['REQUEST_URI']);
if(file_exists($pathOnDisk)) {
// send header with image mime type
echo file_get_contents($pathOnDisk);
exit;
} else {
$matches = array();
$ok = preg_match(
'/\/images\/get\/(\d+)x(\d+)\/(\w+)\.jpg/',
$_SERVER['REQUEST_URI'], $matches);
if(! $ok) {
// invalid url
handleInvalidRequest();
} else {
list(, $width, $height, $guid) = $matches;
// you should do this!
if(isSupportedSize($width, $height)) {
// size is supported. all good
// generate the resized image, save it & output it
} else {
// invalid size requested!!!
handleInvalidRequest();
}
}
}
// snip
function handleInvalidRequest() {
// do something w/ invalid request
// show a default graphic, log it etc
}
?>
Run Code Online (Sandbox Code Playgroud)