我正在用PHP编写一个图片库脚本,并有一个用户将存储他们的图片的单个目录。我正在尝试设置页面缓存,并且只有在目录内容发生变化时才刷新缓存。我认为我可以通过使用filemtime()函数缓存目录的上次修改时间并将其与目录的当前修改时间进行比较来完成此操作。然而,正如我意识到的那样,目录修改时间不会随着文件从该目录添加或删除(至少在Windows上,不确定Linux机器)而改变。如何检查目录内容是否因PHP而改变?
所以我的问题是,检查一个目录的内容是否被修改了最简单的方法是什么?
我正在用PHP编写一个图片库脚本,并有一个用户将存储他们的图片的单个目录。我正在尝试设置页面缓存,并且只有在目录内容发生变化时才刷新缓存。我认为我可以通过使用filemtime()函数缓存目录的上次修改时间并将其与目录的当前修改时间进行比较来完成此操作。然而,正如我意识到的那样,目录修改时间不会随着文件从该目录添加或删除(至少在Windows上,不确定Linux机器)而改变。如何检查目录内容是否因PHP而改变?
所以我的问题是,检查一个目录的内容是否被修改了最简单的方法是什么?
呃。我只是简单地存储一个目录列表的MD5。如果内容改变,则md5(目录列表)将改变。你可能得到非常偶然的md5冲突,但我认为这个机会是足够小的..
或者,您可以在该目录中存储一个小文件,其中包含“最后修改”日期。但我会用md5。
PS。第二个想法,看你如何看待性能(缓存)请求和哈希目录列表可能不是完全最佳..
以下是您可以尝试的方法。将所有图片存储在一个目录中(或者在其内部的/username
子目录中以加快速度并减轻FS的压力),并设置Apache(或您正在使用的连接),将它们作为静态内容提供,并使用“expires-on “未来将达到100年。文件名应该包含一些独特的前缀或后缀(时间戳,文件内容的SHA1哈希等),所以无论何时使用更改文件,其名称将被更改,并且Apache将提供新版本,随后将缓存该文件。
你在想错误的方式。
只要有人上传新文件并将其移至目标位置,您应该立即执行目录索引器脚本。
touching那么用户提交图片后的目录呢? 更新日志说:需要php 5.3才能运行,但我认为它应该适用于所有其他环境
尝试在用户将文件上载到他的目录时删除缓存版本。
当有人试图查看图库时,先查看是否有缓存版本。如果有一个缓存版本,加载它,否则,生成页面,缓存它,完成。
正如其他人所提到的,解决此问题的更好方法是在发生特定事件时触发某个功能,从而更改文件夹。 但是,如果您的服务器是unix,则可以使用inotifywait
来查看目录,然后调用PHP脚本。
这里有一个简单的例子:
#!/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
我一直在寻找类似的东西,我只是发现了这一点:
http://www.franzone.com/2008/06/05/php-script-to-monitor-ftp-directory-changes/
对于我看起来像一个很好的解决方案,因为我有很多控制的(我会做一个AJAX调用看看是否有任何改变)。
希望这可以帮助。
IMO edubem's answer是要走的路,但你可以做这样的事情:
if (sha1(serialize(Map('/path/to/directory/', true))) != /* previous stored hash */)
{
// directory contents has changed
}
还是更弱/更快的版本:
if (Size('/path/to/directory/', true) != /* previous stored size */)
{
// directory contents has changed
}
这里被使用的功能:
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;
}
with inotifywait inside 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";
}
这是一个代码示例,如果目录被更改,它将返回0。 我在备份中使用它。
更改的状态取决于文件及其文件大小的存在。 你可以很容易地改变这一点,文件内容通过更换
$longString .= filesize($file);
与
$longString .= crc32(file_get_contents($file));
比较,但它会影响执行速度。
#!/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');
感谢您的回复,但大多数答案对许多不同系统上许多最终用户都会使用的脚本无效。为了更好地理解我正在实现的目的,请查看http://code.web-geek.net/ck-gallery – PHLAK 2009-02-13 09:54:32