使用PHP和MySQL缓存已调整大小的图像的最佳方法

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)

问候.

  • 谢谢,我已经更新了我的代码,以防他们使用它而不是你的固定版本. (2认同)

pha*_*ckk 5

值得添加的一个注意事项是确保您的代码不会生成这些图像的"未授权"大小.

因此,如果尚不存在,则以下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)