Защита дублирующихся имен файлов путем увеличения - PullRequest
2 голосов
/ 17 февраля 2011

Первое сообщение, и вместо того, чтобы задавать вопрос с предложением ответа на вопрос, на который я не смог найти ответ, может помочь кому-то еще.

Проблема заключалась в локальном сохранении файловых загрузок и попытке найти хороший способ обработки повторяющихся имен файлов.

Учитывая имя файла filename.ext, которое это может сформировать, это даст первое имя файла вида filename- \ d + .ext, которое еще не существует

   $file = "upload.jpg";

   while(is_file($file))
    {
        preg_match("/\d+\.[^.]*$/", $file, $matches);
        if (!$matches)
        {
            $file = preg_replace('/(\.[^.]*)$/', '-1${1}', $file);
            echo $file."<br>";
        }
        else
        {
            list($i, $extension) = explode(".",$matches[0]);

            $file = preg_replace('/(\d+\.[^.]*)$/', ++$i.".".$extension, $file);
        }
 }

  echo $file;

Надеюсь, что это может кому-то помочь

Ответы [ 3 ]

3 голосов
/ 17 февраля 2011

Этот алгоритм не масштабируется.Загрузка n файлов с одинаковыми именами вызовет поведение O ( n ) в этом алгоритме, что приведет к общему времени выполнения O ( n ²), включая O ( n ²) доступ к файловой системе.Это не красиво для серверного приложения.Это также не может быть исправлено из-за того, как работают файловые системы.

Лучшие решения:

  1. Хранить имена файлов, которые уже были использованы в таблице БД, сопоставляя их с их счетом использования.
  2. Ввести метку времени с высокой степенью детализации в имя файла.
  3. Использовать хэш содержимого SHA1 (или MD5) в качестве имени файла.Это также предотвращает загрузку дубликатов файлов, если это важно.

Использование базы данных для сопоставления имен файлов с понятными для человека именами, если необходимо.

1 голос
/ 22 ноября 2011

Лучшее решение - просто прикрепить штамп времени в виде ГГГГДДММЧЧММСС, конфликтов не будет на протяжении всей жизни;) Также его временная сложность очень меньше. Еще одна вещь, которую вы можете сделать ... вы можете пропустить проверку имени напрямую и вместо этого с именем файла ex. «1.jpg», если вы загружаете просто прикрепите 1 (timestamp) .jpg, чтобы вам даже не нужно было перебирать файловую систему. надеюсь, это поможет

ех. в PHP

 $timestamp=date("YmdGis"); 
it will generate something like
20111122193631
;)
0 голосов
/ 16 августа 2012

Я сделал свое собственное решение. Вот оно:

function recursive_increment_filename ($path, $filename)
    {
        $test = "{$path}/{$filename}";
        if (!is_file($test)) return $test;

        $file_info = pathinfo($filename);
        $part_filename = $file_info['filename'];

        if (preg_match ('/(.*)_(\d+)$/', $part_filename, $matches))
        {
            $num = (int)$matches[2] +1;
            $part_filename = $matches[1];
        }
        else
        {
            $num = 1;
        }
        $filename = $part_filename.'_'.$num;

        if (array_key_exists('extension', $file_info))
        {
            $filename .= '.'.$file_info['extension'];
        }

        return recursive_increment_filename($path, $filename);
    }

$url   = realpath(dirname(__FILE__));

$file  = 'test.html';
$fn = recursive_increment_filename($url, $file);

echo $fn;
...