Pregunta

¿Cuál sería la mejor forma de manejar el almacenamiento en caché de imágenes usando PHP?

El nombre del archivo está actualmente almacenado en una base de datos MySQL cuyo nombre se cambia a GUID al cargarlo, junto con el nombre del archivo original y la etiqueta alt.

Cuando la imagen se coloca en las páginas HTML, se hace utilizando una URL como '/images/get/200x200/{guid}.jpg que se reescribe en un script php.Esto permite a mis diseñadores especificar (aproximadamente, la imagen de origen puede ser más pequeña) el tamaño del archivo.

Luego, el script php crea un hash del tamaño (200x200 en la URL) y el nombre del archivo GUID y si el archivo se generó antes (el archivo con el nombre del hash existe en el directorio TMP) envía el archivo desde el directorio TMP de la aplicación.Si el nombre del archivo hash no existe, entonces se crea, se escribe en el disco y se entrega de la misma manera.

¿Es esto tan eficiente como podría ser?(También admite marcas de agua en las imágenes y la configuración de la marca de agua también se almacena en el hash, pero eso está fuera del alcance de esto).

¿Fue útil?

Solución

Hay dos errores tipográficos en el ejemplo de reescritura de Dan Udey (y no puedo comentarlo), debería ser:

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

Saludos.

Otros consejos

Yo lo haría de otra manera.

Problemas:1.Hacer que PHP entregue los archivos es menos eficiente de lo que podría ser.2.PHP tiene que verificar la existencia de archivos cada vez que se solicita una imagen 3.Apache es mucho mejor en esto que PHP.

Hay algunas soluciones aquí.

Puedes usar mod_rewrite en apache.Es posible usar mod_rewrite para probar si existe un archivo y, de ser así, entregarlo en su lugar.Esto evita PHP por completo y hace que las cosas sean mucho más rápidas.Sin embargo, la forma real de hacer esto sería generar un esquema de URL específico que siempre debería existir y luego redirigir a PHP si no es así.

Por ejemplo:

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

Entonces, si un cliente solicita /images/cached/<something> y ese archivo aún no existe, Apache redirigirá la solicitud a /images/generate.php?/images/cached/<something>.Luego, este script puede generar la imagen, escribirla en el caché y luego enviarla al cliente.En el futuro, el script PHP nunca se llamará excepto para imágenes nuevas.

Utilice el almacenamiento en caché.Como decía otro cartel, usa cosas como mod_expires, encabezados de última modificación, etc.para responder a solicitudes GET condicionales.Si el cliente no tiene que volver a solicitar imágenes, las cargas de las páginas se acelerarán drásticamente y la carga en el servidor disminuirá.

Para los casos en los que tenga que enviar una imagen desde PHP, puede usar mod_xsendfile hacerlo con menos gastos generales.Ver la excelente publicación de blog de Arnold Daniels sobre el tema, pero tenga en cuenta que su ejemplo es para descargas.Para servir imágenes en línea, elimine el encabezado Content-Disposition (la tercera llamada al encabezado()).

Espero que esto ayude; más después de que mi migraña desaparezca.

Una nota que vale la pena agregar es asegurarse de que su código no genere " no autorizado " tamaños de estas imágenes.

Entonces, la siguiente URL creará una versión 200x200 de la imagen 1234 si aún no existe una. altamente te sugiero que te asegures de que la URL solicitada contenga dimensiones de imagen que admitas.

/images/get/200x200/1234.jpg

Una persona malintencionada podría comenzar a solicitar URL aleatorias, siempre alterando la altura & amp; ancho de la imagen. Esto causaría a su servidor algunos problemas serios porque estará allí, esencialmente bajo ataque, generando imágenes de tamaños que no admite.

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

Aquí hay un fragmento de código aleatorio que ilustra esto:

<?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 una gran publicación, pero mi problema sigue sin resolverse. No tengo acceso a htaccess en mi proveedor de host, por lo que no se trata de ajustes de apache. ¿Existe realmente una manera de configurar el encabezado de control de cace para las imágenes?

Su enfoque parece bastante razonable: agregaría que se debe implementar algún mecanismo para verificar que la fecha en que se generó la versión en caché fue posterior a la última marca de tiempo modificada del archivo de imagen original (fuente) y, si no, regenerar el caché / versión redimensionada. Esto garantizará que si los diseñadores cambian una imagen, la memoria caché se actualizará adecuadamente.

Eso suena como una forma sólida de hacerlo. El siguiente paso puede ser ir más allá de PHP / MySQL.

Quizás, modifique sus encabezados :

Si está usando PHP para enviar tipos MIME, también puede usar encabezados 'Keep-alive' y 'Cache-control' para extender la vida útil de sus imágenes en el servidor y eliminar parte de la carga de PHP / MySQL.

Además, considere también los complementos de apache para el almacenamiento en caché. Como mod_expires .

Oh, una cosa más, ¿cuánto control tienes sobre tu servidor? ¿Deberíamos limitar esta conversación a solo PHP / MySQL?

He logrado hacer esto simplemente usando un encabezado de redireccionamiento en 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");
}

En lugar de mantener la dirección del archivo en la base de datos, prefiero agregar un número aleatorio al nombre del archivo cada vez que el usuario inicia sesión. Algo así para el usuario 1234: image / picture_1234.png? rnd = 6534122341

Si el usuario envía una nueva imagen durante la sesión, simplemente actualizo el número aleatorio.

GUID aborda el problema de caché al 100%. Sin embargo, hace que sea más difícil hacer un seguimiento de los archivos de imagen. Con este método, existe la posibilidad de que el usuario vuelva a ver la misma imagen en un inicio de sesión futuro. Sin embargo, las probabilidades son bajas si genera su número aleatorio a partir de mil millones de números.

phpThumb es un marco que genera imágenes / miniaturas redimensionadas sobre la marcha. También implementa el almacenamiento en caché y es muy fácil de implementar.

El código para cambiar el tamaño de una imagen es:

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

le dará una miniatura de 200 x 200;

También admite marcas de agua.

Compruébalo en: http://phpthumb.sourceforge.net/

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top