通过增量重复保护文件名

时间:2011-02-17 18:12:52

标签: php file duplicates filenames increment

第一篇文章,而不是提出一个问题,提出一个我无法找到答案的答案,可能会帮助其他人。

问题是在本地保存文件上传,并试图找到处理重复文件名的好方法。

给定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 个答案:

答案 0 :(得分:3)

此算法不可扩展。上传具有相同名称的 n 文件将导致此算法中的O( n )行为,从而导致O( n ²)总运行时间,包括O( n ²)文件系统访问。这对于服务器应用来说并不合适。由于文件系统的工作方式,它也无法修复。

更好的解决方案:

  1. 存储已在数据库表中使用的文件名,并将其映射到其使用计数。
  2. 在文件名中加上一个高粒度的时间戳。
  3. 使用内容的SHA1(或MD5)哈希作为文件名。如果这很重要,这也可以防止重复上传文件。
  4. 如有必要,使用数据库将文件名映射回人类可读的名称。

答案 1 :(得分:1)

最佳解决方案是以YYYYDDMMHHMMSS的形式附上时间戳,你不会在一生中遇到冲突;) 它的时间复杂度也非常低。 你可以做的另一件事......你可以直接跳过名字检查,而不是文件名ex。 “1.jpg”如果您正在上传 只需附加1(时间戳).jpg,这样您甚至不需要遍历文件系统。希望它有所帮助

离。用PHP

 $timestamp=date("YmdGis"); 
it will generate something like
20111122193631
;)

答案 2 :(得分:0)

我已经制定了自己的解决方案。这是:

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;