Кэширование изображений в PHP - PullRequest
3 голосов
/ 23 февраля 2012

Это работает просто отлично.

Но проблема в том, что изображение меняется, но имеет то же имя.Моя система кэширования распознает, что изображение изменилось, и удаляет старый кэшированный файл и создает новый, а затем передает этот новый измененный размер кэшированного файла из моего собственного кэша.Но есть проблема с кешем моей системы или веб-браузера.

Когда изображение изменяется, мой скрипт отправляет заголовок 200 OK (для измененного файла) ... Но предварительный просмотр изображения не меняется, и ответ 200 OK, пока я не нажму F5 вручную в браузере.Затем он отправляет еще раз 200 OK и меняет изображение, и с этого момента он отправляет 304 Не изменено (как и должно быть).Но проблема в том, что я должен нажать F5, чтобы изменить кэшированное изображение браузера ... Я не знаю, почему 200 OK не меняет кэшированный файл браузера ...

Код:

<?php

// Image manipulation script

include("../../../Init.php");

if(!isset($_GET["File"]))
    return;

$sFullFile = urldecode($_GET["File"]);

$pData = pathinfo($sFullFile);

// Options
$sActions = isset($_GET["Actions"]) ? $_GET["Actions"] : "";
$iMaxWidth = isset($_GET["MaxWidth"]) ? (int)$_GET["MaxWidth"] : 0;
$iMaxHeight = isset($_GET["MaxHeight"]) ? (int)$_GET["MaxHeight"] : 0;
$bSaveAspect = isset($_GET["SaveAspect"]) & $_GET["SaveAspect"] == "0" ? false : true;

// Cache control
$sPathCacheString = md5($pData["dirname"]);
$sFileCacheString = md5($pData["basename"]);
$pLastModTime = filemtime($sFullFile);
$sOptCacheString = md5($sActions . $iMaxWidth . $iMaxHeight . $bSaveAspect);

$sCacheFile = ImageCache::GetImageManipulatorCacheFileName($sFullFile, $sActions, $iMaxWidth, $iMaxHeight, $bSaveAspect);

header("Cache-Control: private, max-age=2592000, pre-check=2592000, must-revalidate");
header("Pragma: private");
header("Expires: " . date(DATE_RFC822, strtotime(" 30 day")));

$sLastModString = gmdate("D, d M Y H:i:s \G\M\T", $pLastModTime);
if(isset($_SERVER["HTTP_IF_MODIFIED_SINCE"]) && strtotime($_SERVER["HTTP_IF_MODIFIED_SINCE"]) >= $pLastModTime)
{
    header("HTTP/1.0 304 Not Modified");
    return;
}
else
{
    $pImage = new Image($sFullFile);

    @unlink($sCacheFile);

    if(GetFlag("ResizeMax", $sActions))
    {
        if($pImage->GetWidth() > $iMaxWidth || $pImage->GetHeight() > $iMaxHeight)
            $pImage->ResizeImage($iMaxWidth, $iMaxHeight, $bSaveAspect);
    }

    Cache::WriteFile($sCacheFile, $pImage->GetOutput());    

    header("Last-Modified: $sLastModString");
    header("Content-type: " . $pImage->GetMIMEType());
    $pImage->Destroy();

    Cache::StreamOut($sCacheFile);
}


/*

    Copyright (C) 2010. Determinanta
    http://www.determinanta.hr
    Part of WebSuite aplication platform. All rights reserved.

*/


?>

РЕДАКТИРОВАТЬ: РЕШЕНО

Я решил ... Проблема была в проверке $ _SERVER ["HTTP_IF_MODIFIED_SINCE"] ... Теперь я просто обслуживаю кэшированный файл всегда, если он не изменен.Мне потребовалось все утро, чтобы решить эту проблему ... Спасибо за ваш вклад, ребята.Приветствия.

<?php

// Image manipulation script

include("../../../Init.php");

if(!isset($_GET["File"]))
    return;

$sFullFile = urldecode($_GET["File"]);

$pData = pathinfo($sFullFile);

// Options
$sActions = isset($_GET["Actions"]) ? $_GET["Actions"] : "";
$iMaxWidth = isset($_GET["MaxWidth"]) ? (int)$_GET["MaxWidth"] : 0;
$iMaxHeight = isset($_GET["MaxHeight"]) ? (int)$_GET["MaxHeight"] : 0;
$bSaveAspect = isset($_GET["SaveAspect"]) & $_GET["SaveAspect"] == "0" ? false : true;

// Cache control
$sPathCacheString = md5($pData["dirname"]);
$sFileCacheString = md5($pData["basename"]);
$pLastModTime = filemtime($sFullFile);
$sOptCacheString = md5($sActions . $iMaxWidth . $iMaxHeight . $bSaveAspect);

$sCacheFile = ImageCache::GetImageManipulatorCacheFileName($sFullFile, $sActions, $iMaxWidth, $iMaxHeight, $bSaveAspect);
$sFullCacheFile = CACHE_PATH . "/" . $sCacheFile;

$bCacheNotModified = true;
if(!is_file($sFullCacheFile))
    $bCacheNotModified = false;
else
{
    if(filemtime($sFullCacheFile) != $pLastModTime)
        $bCacheNotModified = false;
}

$sLastModString = gmdate("D, d M Y H:i:s \G\M\T", $pLastModTime);
if($bCacheNotModified)
{
    header("HTTP/1.0 304 Not Modified");
    return;
}
else
{               
    $pImage = new Image($sFullFile);

    @unlink($sCacheFile);

    if(GetFlag("ResizeMax", $sActions))
    {
        if($pImage->GetWidth() > $iMaxWidth || $pImage->GetHeight() > $iMaxHeight)
            $pImage->ResizeImage($iMaxWidth, $iMaxHeight, $bSaveAspect);
    }

    Cache::WriteFile($sCacheFile, $pImage->GetOutput());
    touch($sFullCacheFile, $pLastModTime);

    header("Cache-Control: private, max-age=2592000, pre-check=2592000, must-revalidate");
    header("Pragma: private");
    header("Expires: " . date(DATE_RFC822, 0));
    header("Last-Modified: $sLastModString");
    header("ETag: \"" . $sImageMD5 . "\"");
    header("Content-type: " . $pImage->GetMIMEType());

    $pImage->Destroy();

    Cache::StreamOut($sCacheFile);
}


/*

    Copyright (C) 2010. Determinanta
    http://www.determinanta.hr
    Part of WebSuite aplication platform. All rights reserved.

*/


?>

Ответы [ 2 ]

0 голосов
/ 23 февраля 2012

Вы пробовали установить ETags (Entity Tags) в заголовках изображений?

MD5 изображение в переменную, затем установите ETag так:

header("ETag: \"".$img_md5."\");
0 голосов
/ 23 февраля 2012

Проблема, с которой вы столкнулись - это браузер. Я также пытался бороться с этим с помощью кодов ответов и заголовков, но, в конце концов, единственный верный способ заставить браузер захватить новое изображение - это добавить уникальную строку в URL, такую ​​как отметка времени. Одно простое решение заключается в том, что при изменении изображения добавьте текущую временную метку в ваш источник HTML следующим образом:

<img src="path/to/your/php/script.php?<?= time(); ?>"/>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...