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

时间:2020-03-06 14:47:43  来源:igfitidea点击:

使用PHP处理图像缓存的最佳实践方法是什么。

该文件名当前存储在一个MySQL数据库中,该数据库在上载时已重命名为GUID,以及原始文件名和alt标签。

将图像放入HTML页面后,可以使用重写为php脚本的url(例如'/images/get/200x200/{guid}.jpg)来完成。这使我的设计人员可以指定文件大小(大约比源图像小)。

然后,PHP脚本会创建一个大小为(URL中为200x200)的哈希值和GUID文件名,并且如果该文件是在之前生成的(带有哈希名称的文件存在于TMP目录中)从应用程序TMP目录发送文件。如果散列的文件名不存在,则将其创建,写入磁盘并以相同的方式提供服务,

这样有效吗? (它还支持对图像加水印,并且水印设置也存储在哈希中,但这超出了此范围。)

解决方案

方法似乎很合理,我想补充一点,应该采用某种机制来检查缓存版本的生成日期是否在原始(源)映像文件的最后修改时间戳之后,如果不重新生成缓存/调整大小的版本。这将确保如果设计者更改了图像,则缓存将被适当地更新。

听起来这是一种可靠的方法。下一步可能是超越PHP / MySQL。

也许,调整标题:

如果我们使用PHP发送MIME类型,则还可以使用" Keep-alive"和" Cache-control"标头来延长服务器上图像的寿命,并减轻PHP / MySQL的负担。

另外,还要考虑使用apache插件进行缓存。就像mod_expires。

哦,还有一件事,我们对服务器有多少控制权?我们是否应该将此对话限制为仅PHP / MySQL?

phpThumb是一个框架,可动态生成调整大小的图像/缩略图。它还实现了缓存,并且非常容易实现。

调整图像大小的代码是:

<img src="/phpThumb.php?src=/path/to/image.jpg&w=200&amp;h=200" alt="thumbnail"/>

将为我们提供200 x 200的缩略图;

它还支持水印。

在以下位置查看:
http://phpthumb.sourceforge.net/

值得一提的是要确保代码不会生成这些图像的"未经授权"大小。

因此,如果以下网址不存在,则会创建一个200x200版本的图像1234. 我强烈建议我们确保所请求的URL包含我们支持的图像尺寸。

/images/get/200x200/1234.jpg

恶意者可能会开始请求随机URL,从而始终更改图像的高度和宽度。这将导致服务器由于坐在那里而受到严重威胁,这实际上会受到攻击,生成我们不支持的大小的图像。

/images/get/0x1/1234.jpg
/images/get/0x2/1234.jpg
...
/images/get/0x9999999/1234.jpg
/images/get/1x1/1234.jpg
...
etc

这是一个随机的代码片段,说明了这一点:

<?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
    }
?>

我会以不同的方式来做。

问题:
1.让PHP提供文件服务的效率比以前要低。
2.每次请求图像时,PHP都要检查文件是否存在
3. Apache在这方面远胜过PHP。

这里有一些解决方案。

我们可以在Apache上使用mod_rewrite。可以使用mod_rewrite测试文件是否存在,如果存在,则改为提供该文件。这将完全绕过PHP,并使处理过程更快。但是,执行此操作的真正方法是生成始终应存在的特定URL模式,然后如果不存在则重定向到PHP。

例如:

RewriteCond %{REQUEST_URI} ^/images/cached/
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteRule (.*) /images/generate.php? [L]

因此,如果客户端请求/ images / cached / &lt;something>并且该文件尚不存在,Apache会将请求重定向到/images/generate.php?/images/cached/ &lt;something>。然后,该脚本可以生成图像,将其写入高速缓存,然后将其发送给客户端。将来,除了新映像外,永远不会调用PHP脚本。

使用缓存。就像另一位发布者所说的那样,使用诸如mod_expires,Last-Modified头等之类的东西来响应条件GET请求。如果客户端不必重新请求图像,则页面加载将大大加快,服务器上的负载将减少。

对于必须从PHP发送图像的情况,可以使用mod_xsendfile来减少开销。请参阅有关此问题的Arnold Daniels的精彩博客文章,但请注意,他的示例可供下载。要内联提供图像,请取出Content-Disposition标头(第三个header()调用)。

希望这在我的偏头痛消除后能有所帮助。

似乎很棒的帖子,但是我的问题仍然没有解决。我没有在主机提供商中访问htaccess的权限,因此没有关于apache调整的问题。真的有办法为图像设置cace-control标头吗?

我已经成功地使用PHP中的重定向标头来做到这一点:

if (!file_exists($filename)) {  

    // *** Insert code that generates image ***

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

    // Output
    readfile($filename);    

} else {
    // Redirect
    $host  = $_SERVER['HTTP_HOST'];
    $uri   = rtrim(dirname($_SERVER['PHP_SELF']), '/\');
    $extra = $filename;
    header("Location: http://$host$uri/$extra");
}

Dan Udey的重写示例中有两种错别字(我无法对此发表评论),它应该是:

RewriteCond %{REQUEST_URI} ^/images/cached/
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteRule (.*) /images/generate.php? [L]

问候。

我宁愿在用户登录时在文件名中添加一个随机数,而不是将文件地址保留在db中。用户1234之类的东西是:image / picture_1234.png?rnd = 6534122341

如果用户在会话期间提交了新图片,则只需刷新随机数即可。

GUID 100%解决了缓存问题。但是,这使得跟踪图片文件更加困难。使用这种方法,用户有可能在以后的登录时再次看到同一张图片。但是,如果我们从十亿个数字中生成随机数,则赔率很低。