Nasıl dizin içeriğini PHP ile değişti olmadığını kontrol etmek?

9 Cevap php

PHP bir fotoğraf galerisi komut dosyası yazma ve kullanıcı kendi fotoğraflarını saklamak olacak bir tek dizin var ediyorum. Ben sayfa önbelleğe kurmak ve dizinin içeriği değişti eğer önbellek yalnızca yenilemek için çalışılıyor. Ben filemtime () işlevini kullanarak dizinin son değiştirilme zamanı önbelleğe alarak yapmak ve dizinin şimdiki değiştirilmiş kıyaslayın düşündüm. Ben gerçekleştirmek için geldim gibi dosya (henüz Linux makineleri konusunda emin değil, en azından Windows,) bu dizinden eklenir veya kaldırılır Ancak, dizin değiştirilen zaman değişmez.

Yani, bir dizinin içeriği değiştirilmiş olmadığını kontrol etmek için basit yolu nedir benim sorular olduğunu?

9 Cevap

Uh. I'd simply store the md5 of a directory listing. If the contents change, the md5(directory-listing) will change. You might get the very occasional md5 clash, but I think that chance is tiny enough..
Alternatively, you could store a little file in that directory that contains the "last modified" date. But I'd go with md5.


PS. İkinci düşünce, performans (önbelleğe alma) isteyen ve dizin listeleme tamamen uygun olmayabilir karma bakıyoruz ne gibi görerek ..

As already mentioned by others, a better way to solve this would be to trigger a function when particular events happen, that changes the folder. However, if your server is a unix, you can use inotifywait to watch the directory, and then invoke a PHP script.

İşte basit bir örnek:

#!/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

Ayrıca bakınız: http://linux.die.net/man/1/inotifywait

php iç inotifywait ile

$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";
}

Burada deneyebilirsiniz buydu. Tek bir dizindeki tüm resimlerinizi saklayabileceğiniz (veya içine /username altdizinlere şeyleri hızlandırmak ve FS üzerindeki stresi azaltmak için) ve Apache (veya whaterver kullandığınız) gibi statik onlara hizmet için kurulmuş içerik "sona eriyor-on" gelecekte 100 yıl ayarlanır. Dosya adları bazı benzersiz bir önek veya sonek (zaman damgası, dosya içeriğinin SHA1, vb) içerir, bu nedenle kullanımları adını değiştirdi alır dosyasını değiştirir ve Apache yol boyunca önbelleğe alacak yeni bir sürümünü, hizmet edecek her. Gerekir

Sen yanlış bir şekilde düşünüyoruz.

Size en kısa sürede Birinin yeni bir dosya yükledi ve hedef konuma taşınmış gibi rehberi dizinleyicisi komut yürütmek gerekir.

IMO edubem's answer gitmek için bir yoldur, ancak böyle bir şey yapabilirsiniz:

if (sha1(serialize(Map('/path/to/directory/', true))) != /* previous stored hash */)
{
    // directory contents has changed
}

Ya da daha zayıf / hızlı sürümü:

if (Size('/path/to/directory/', true) != /* previous stored size */)
{
    // directory contents has changed
}

Burada kullanılan fonksiyonlar şunlardır:

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

Bir kullanıcı kendi dizine bir dosya yüklediği zaman önbelleğe alınmış sürümünü silmeyi deneyin.

Birisi galeriyi görüntülemek için çalıştığında önbelleğe alınmış bir sürümü birinci varsa, bak. Önbelleğe alınmış bir sürümü varsa, aksi yüklemek sayfasını oluşturmak, önbelleğe, bitti.

Ben benzer ve ben sadece bunu buldum şey arıyordu:

http://www.franzone.com/2008/06/05/php-script-to-monitor-ftp-directory-changes/

(Ben bir şey değişti görmek için bir AJAX çağrısı yapıyor olacak) kontrolü bir çok olacak beri bana büyük bir çözüm gibi görünüyor için.

Bu yardımcı olur umarım.

Here is a code sample, that would return 0 if the directory was changed. I use it in backups.

The changed status is determined by presence of files and their filesizes. You could easily change this, to compare file contents by replacing

$longString .= filesize($file);

ile

$longString .= crc32(file_get_contents($file));

ancak yürütme hızını etkileyecektir.

#!/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');