在PHP中生成随机字符串作为文件名

9
我该如何创建一个随机文本字符串用于文件名?
我正在上传照片并在完成后重命名它们。所有照片都将存储在一个目录中,因此它们的文件名需要是唯一的。
是否有标准的方法来实现这个?
是否有一种检查文件名是否已存在的方法?
这是为单用户环境(我自己)设计的,用于展示我个人网站上的照片,但我想要自动化一些操作。我不必担心两个用户同时尝试上传并生成相同的文件名,但我确实想要检查它是否已经存在。
我知道如何上传文件,也知道如何生成随机字符串,但想知道是否有标准方式实现。

你尝试过什么吗?请发布你所做的内容。 - skjcyber
请查看此问题的链接:https://dev59.com/3W855IYBdhLWcg3waDiR - TheWolf
3个回答

40

正确的方法是使用PHP的tempnam()函数。它可以在指定目录中创建一个带有保证唯一名称的文件,因此您不必担心随机性或覆盖现有文件:

$filename = tempnam('/path/to/storage/directory', '');
unlink($filename);
move_uploaded_file($_FILES['file']['tmp_name'], $filename);

我该如何将您的代码与Domecraft的代码结合使用?我想要更长的文件名。 - Michael
4
你可以使用@Domecraft的代码生成一个随机字符串,然后将其作为第二个参数传递给tempnam()函数。它将会被添加为文件名的前缀。 - George Brighton
这是正确的,但是通过 unlink() 删除它会引入一个问题。如果需要安全性的唯一文件名,则可能不可行。 - Douglas

31
function random_string($length) {
    $key = '';
    $keys = array_merge(range(0, 9), range('a', 'z'));

    for ($i = 0; $i < $length; $i++) {
        $key .= $keys[array_rand($keys)];
    }

    return $key;
}

echo random_string(50);

示例输出:

zsd16xzv3jsytnp87tk7ygv73k8zmr0ekh6ly7mxaeyeh46oe8

编辑

将此文件夹内的内容设为唯一值,更改以下函数:

function random_filename($length, $directory = '', $extension = '')
{
    // default to this files directory if empty...
    $dir = !empty($directory) && is_dir($directory) ? $directory : dirname(__FILE__);

    do {
        $key = '';
        $keys = array_merge(range(0, 9), range('a', 'z'));

        for ($i = 0; $i < $length; $i++) {
            $key .= $keys[array_rand($keys)];
        }
    } while (file_exists($dir . '/' . $key . (!empty($extension) ? '.' . $extension : '')));

    return $key . (!empty($extension) ? '.' . $extension : '');
}

// Checks in the directory of where this file is located.
echo random_filename(50);

// Checks in a user-supplied directory...
echo random_filename(50, '/ServerRoot/mysite/myfiles');

// Checks in current directory of php file, with zip extension...
echo random_filename(50, '', 'zip');

谢谢,这正是我想要的。我以前做过类似的事情,但不确定这是否足够“健壮”。 - Michael
我试图立即完成,但我必须离开几分钟。现在已经完成了。 - Michael
8
该解决方案不能保证唯一性——字符串生成过程中没有考虑现有的文件。 - George Brighton
1
是的,但他不必知道。 - Domecraft
你需要一些上下文 - 否则就没有什么可以进行比较以确保唯一性。这就是为什么 tempnam() 函数需要一个目录的原因 :) - George Brighton
谢谢。你能编辑我的答案,让它显示出来吗? - Domecraft

1
希望这就是您要找的内容:
<?php
function generateFileName()
{
$chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789_";
$name = "";
for($i=0; $i<12; $i++)
$name.= $chars[rand(0,strlen($chars))];
return $name;
}
//get a random name of the file here
$fileName = generateName();
//what we need to do is scan the directory for existence of the current filename
$files = scandir(dirname(__FILE__).'/images');//assumed images are stored in images directory of the current directory
$temp = $fileName.'.'.$_FILES['assumed']['type'];//add extension to randomly generated image name
for($i = 0; $i<count($files); $i++)
  if($temp==$files[$i] && !is_dir($files[$i]))
   {
     $fileName .= "_1.".$_FILES['assumed']['type'];
     break;
   }
 unset($temp);
 unset($files);
 //now you can upload an image in the directory with a random unique file name as you required
 move_uploaded_file($_FILES['assumed']['tmp_name'],"images/".$fileName);
 unset($fileName);
?>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接