remove - ¿Cómo verificar si el contenido del directorio ha cambiado con PHP?
strip_tags wordpress (10)
Estoy escribiendo un script de galería de fotos en PHP y tengo un único directorio donde el usuario almacenará sus imágenes. Estoy intentando configurar el almacenamiento en caché de la página y actualizar la caché solo si el contenido del directorio ha cambiado. Pensé que podría hacer esto almacenando en caché la última hora modificada del directorio utilizando la función filemtime () y compararla con la hora de modificación actual del directorio. Sin embargo, como me he dado cuenta, el tiempo de modificación del directorio no cambia ya que los archivos se agregan o eliminan de ese directorio (al menos en Windows, aún no estoy seguro acerca de las máquinas con Linux).
Entonces, mi pregunta es, ¿cuál es la forma más sencilla de verificar si los contenidos de un directorio han sido modificados?
Intente eliminar la versión en caché cuando un usuario carga un archivo en su directorio.
Cuando alguien intenta ver la galería, mira primero si hay una versión en caché. Si hay una versión almacenada en caché, cárguela; de lo contrario, genere la página, la guarde en caché y termine.
Como ya se mencionó por otros, una mejor manera de resolver esto sería activar una función cuando suceden eventos particulares, que cambia la carpeta. Sin embargo, si su servidor es unix, puede usar inotifywait
para ver el directorio y luego invocar un script PHP.
Aquí hay un ejemplo simple:
#!/bin/sh
inotifywait --recursive --monitor --quiet --event modify,create,delete,move --format ''%f'' /path/to/directory/to/watch |
while read FILE ; do
php /path/to/trigger.php $FILE
done
Ver también: http://linux.die.net/man/1/inotifywait
Estás pensando de la manera incorrecta.
Debe ejecutar su secuencia de comandos del indexador de directorios tan pronto como alguien cargue un nuevo archivo y se mueva a la ubicación de destino.
Esto es lo que puedes probar. Almacene todas las imágenes en un solo directorio (o en subdirectorios /username
dentro de él para acelerar las cosas y disminuir el estrés en el FS) y configure Apache (o lo que quiera que esté usando) para que les sirva como contenido estático con "expira- en "establecido en 100 años en el futuro". Los nombres de archivo deben contener algún prefijo o sufijo único (marca de tiempo, SHA1 hash de contenido de archivo, etc.), de modo que cada vez que se utiliza el archivo cambia su nombre cambia y Apache publicará una nueva versión, que se almacenará en caché en el camino.
¿Qué hay de tocar el directorio después de que un usuario ha enviado su imagen? Changelog dice: Requiere php 5.3 para que Windows funcione, pero creo que debería funcionar en todos los demás entornos
Uh. Simplemente almacenaría el md5 de una lista de directorios. Si el contenido cambia, el md5 (directorio-listado) cambiará. Es posible que tengas el choque ocasional de md5, pero creo que esa posibilidad es lo suficientemente pequeña.
Alternativamente, podría almacenar un pequeño archivo en ese directorio que contenga la fecha de "última modificación". Pero iría con md5.
PD. pensándolo bien, al ver cómo estás viendo el rendimiento (almacenamiento en caché), solicitar y mezclar la lista del directorio podría no ser del todo óptimo.
Estaba buscando algo similar y acabo de encontrar esto:
http://www.franzone.com/2008/06/05/php-script-to-monitor-ftp-directory-changes/
Para mí, parece una gran solución ya que tendré mucho control (haré una llamada AJAX para ver si algo ha cambiado).
Espero que esto ayude
con inotifywait dentro de php
$watchedDir = ''watch'';
$in = popen("inotifywait --monitor --quiet --format ''%e %f'' --event create,moved_to ''$watchedDir''", ''r'');
if ($in === false)
throw new Exception (''fail start notify'');
while (($line = fgets($in)) !== false)
{
list($event, $file) = explode('' '', rtrim($line, PHP_EOL), 2);
echo "$event $file/n";
}
Aquí hay un ejemplo de código, que devolvería 0 si se cambió el directorio. Lo uso en copias de seguridad.
El estado modificado está determinado por la presencia de archivos y sus tamaños de archivo. Podrías cambiar esto fácilmente, para comparar el contenido del archivo reemplazando
$longString .= filesize($file);
con
$longString .= crc32(file_get_contents($file));
pero afectará la velocidad de ejecución.
#!/usr/bin/php
<?php
$dirName = $argv[1];
$basePath = ''/var/www/vhosts/majestichorseporn.com/web/'';
$dataFile = ''./backup_dir_if_changed.dat'';
# startup checks
if (!is_writable($dataFile))
die($dataFile . '' is not writable!'');
if (!is_dir($basePath . $dirName))
die($basePath . $dirName . '' is not a directory'');
$dataFileContent = file_get_contents($dataFile);
$data = @unserialize($dataFileContent);
if ($data === false)
$data = array();
# find all files ang concatenate their sizes to calculate crc32
$files = glob($basePath . $dirName . ''/*'', GLOB_BRACE);
$longString = '''';
foreach ($files as $file) {
$longString .= filesize($file);
}
$longStringHash = crc32($longString);
# do changed check
if (isset ($data[$dirName]) && $data[$dirName] == $longStringHash)
die(''Directory did not change.'');
# save hash do DB
$data[$dirName] = $longStringHash;
file_put_contents($dataFile, serialize($data));
die(''0'');
La respuesta de IMO edubem es el camino a seguir, sin embargo, puedes hacer algo como esto:
if (sha1(serialize(Map(''/path/to/directory/'', true))) != /* previous stored hash */)
{
// directory contents has changed
}
O una versión más débil / más rápida:
if (Size(''/path/to/directory/'', true) != /* previous stored size */)
{
// directory contents has changed
}
Estas son las funciones utilizadas:
function Map($path, $recursive = false)
{
$result = array();
if (is_dir($path) === true)
{
$path = Path($path);
$files = array_diff(scandir($path), array(''.'', ''..''));
foreach ($files as $file)
{
if (is_dir($path . $file) === true)
{
$result[$file] = ($recursive === true) ? Map($path . $file, $recursive) : $this->Size($path . $file, true);
}
else if (is_file($path . $file) === true)
{
$result[$file] = Size($path . $file);
}
}
}
else if (is_file($path) === true)
{
$result[basename($path)] = Size($path);
}
return $result;
}
function Size($path, $recursive = true)
{
$result = 0;
if (is_dir($path) === true)
{
$path = Path($path);
$files = array_diff(scandir($path), array(''.'', ''..''));
foreach ($files as $file)
{
if (is_dir($path . $file) === true)
{
$result += ($recursive === true) ? Size($path . $file, $recursive) : 0;
}
else if (is_file() === true)
{
$result += sprintf(''%u'', filesize($path . $file));
}
}
}
else if (is_file($path) === true)
{
$result += sprintf(''%u'', filesize($path));
}
return $result;
}
function Path($path)
{
if (file_exists($path) === true)
{
$path = rtrim(str_replace(''//', ''/'', realpath($path)), ''/'');
if (is_dir($path) === true)
{
$path .= ''/'';
}
return $path;
}
return false;
}