Pergunta

Qual seria a melhor maneira prática de lidar com o cache de imagens usando PHP.

O nome do arquivo está armazenado em um banco de dados MySQL, que é renomeado para um GUID no upload, juntamente com a tag nome do arquivo e alt originais.

Quando a imagem é colocada em páginas HTML é feito usando um url como '/images/get/200x200/{guid}.jpg que é reescrito para um script php. Isso permite que os meus designers para especificar (aproximadamente - a imagem de origem talvez menor) o tamanho do arquivo.

O script php, em seguida, cria um hash do tamanho (200x200 na url) e o nome do arquivo GUID e se o arquivo foi gerado antes (arquivo com o nome do hash existe no diretório TMP) envia o arquivo da aplicação tmp. Se o nome do arquivo hash não existe, então ele é criado, gravado em disco e serviu-se da mesma maneira,

Este é eficiente quanto poderia ser? (Ele também suporta marca d'água nas imagens e as configurações de marca d'água são armazenadas no hash, bem como, mas isso é fora do escopo para isso.)

Foi útil?

Solução

Há dois erros no exemplo de reescrita de Dan Udey (e eu não posso comentar sobre isso), ele deve sim ser:

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

Cumprimentos.

Outras dicas

Eu faria isso de uma maneira diferente.

Problemas: 1. Tendo PHP servir os arquivos para fora é menos eficiente do que poderia ser. 2. PHP tem de verificar a existência de arquivos a cada vez que uma imagem é solicitada 3. Apache é muito melhor nisso do que PHP nunca vai ser.

Existem algumas soluções aqui.

Você pode usar mod_rewrite no Apache. É possível usar o mod_rewrite para teste para ver se existe um arquivo, e se assim, servir a esse arquivo em vez. Isso ignora PHP inteiramente, e torna as coisas muito mais rápido. A forma real de fazer isso, porém, seria a de gerar um esquema URL específica que deve sempre existir, e depois redirecionar para PHP se não.

Por exemplo:

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

Portanto, se um cliente solicita /images/cached/<something> e esse arquivo não existir, o Apache irá redirecionar o pedido para /images/generate.php?/images/cached/<something>. Este script pode gerar a imagem, escrevê-lo para o cache, e depois enviá-lo para o cliente. No futuro, o script PHP nunca é chamado, exceto para as novas imagens.

Use cache. Como outra com dossel disse, usar coisas como mod_expires, cabeçalhos Last-Modified, etc. Para responder a solicitações GET condicionais. Se o cliente não tem de imagens re-pedido, carrega a página irá acelerar drasticamente, e carga sobre o servidor irá diminuir.

Para casos em que você tem que enviar uma imagem do PHP, você pode usar mod_xsendfile fazê-lo com menos sobrecarga. Consulte o excelente blog de Arnold Daniels sobre a questão, mas note que o seu exemplo é para downloads. Para servir imagens em linha, tirar o cabeçalho Content-Disposition (o terceiro header () chamada).

Espero que isso ajude -. Mais depois da minha enxaqueca apura-se

Uma pena nota adicionando é ter certeza de que você está código não gera tamanhos "não autorizadas" dessas imagens.

Então, o seguinte URL criará uma versão 200x200 de imagem 1234 se ainda não existir. Eu tinha altamente sugiro que você se certificar de que o URL solicitado contém dimensões da imagem que você suporta.

/images/get/200x200/1234.jpg

Uma pessoa mal intencionada poderia começar a pedir URLs aleatórias, sempre alterando a altura e largura da imagem. Isso faria com que o servidor alguns problemas sérios b / c ele vai estar sentado lá, essencialmente sob ataque, gerando imagens de tamanhos que não suportam.

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

Aqui está um recorte aleatória de código ilustrando esta:

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

Parece ótimo post, mas o meu problema ainda permanece sem solução. Eu não tenho acesso a htaccess no meu provedor de hospedagem, então não há dúvida de apache ajustes. Existe realmente uma maneira de definir cabeçalho de controle de cace para imagens?

A sua abordagem parece bastante razoável - Gostaria de acrescentar que algum mecanismo deve ser posta em prática para verificar se a data em que a versão em cache foi gerado foi após o último timestamp modificada do arquivo de imagem original (fonte) e se não regenerar o cache / versão redimensionada. Isso irá garantir que, se uma imagem é alterada pelos designers do cache será atualizado de forma adequada.

Isso soa como um caminho sólido para fazê-lo. O próximo passo pode ser a de ir além de PHP / MySQL.

Talvez, ajustar seus cabeçalhos :

Se você estiver usando PHP para enviar tipos MIME, você também pode usar cabeçalhos 'keep-alive' e 'Cache-control' para prolongar a vida de suas imagens no servidor e tirar um pouco da carga fora de PHP / MySQL.

Além disso, considere apache plug-in (s) para armazenamento em cache também. Como mod_expires .

Oh, mais uma coisa, quanto controle você tem sobre o seu servidor? Devemos limitar essa conversa para apenas PHP / MySQL?

Eu consegui fazer isso simplesmente usando um cabeçalho de redirecionamento no 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");
}

Em vez de manter o endereço do arquivo no db Eu prefiro adicionando um número aleatório para o nome do arquivo sempre que o usuário fizer logon em algo assim para o usuário 1234:.? Image / picture_1234.png rnd = 6534122341

Se os submete usuário uma nova imagem durante a sessão eu apenas atualizar o número aleatório.

tackles GUID o problema de cache de 100%. No entanto, espécie de faz com que seja mais difícil de manter o controle dos arquivos de imagem. Com este método há uma chance de que o usuário pode ver a mesma imagem novamente a um login futuro. No entanto as probabilidades são baixas se você gerar o número aleatório de um bilhão de números.

phpThumb é uma estrutura que gera imagens redimensionadas / miniaturas na mosca. Ele também implementa cache e é muito fácil de implementar.

O código para redimensionar uma imagem é:

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

lhe dará uma miniatura de 200 x 200;

Ele também suporta marca d'água.

Confira em: http://phpthumb.sourceforge.net/

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top