真正独特的随机数由PHP生成?

时间:2010-05-14 11:42:08

标签: php php4 flawed-concept

我已经构建了一个php脚本来托管用户上传的大量图片,为图像文件名生成随机数的最佳方法是什么,以便将来不会出现文件名冲突?就像Imageshack一样。感谢。

10 个答案:

答案 0 :(得分:11)

$better_token = uniqid(md5(mt_rand()), true);

答案 1 :(得分:9)

最简单的方法是为每个文件添加新的GUID。

http://www.php.net/manual/en/function.uniqid.php#65879

答案 2 :(得分:2)

以下是我实施解决方案的方法

此示例假设我想要

  • 获取一个列表,其中包含50个唯一且随机的数字
  • 此#列表来自0到1000的数字范围

代码:

 //developed by www.fatphuc.com

 $array = array(); //define the array

 //set random # range
 $minNum = 0;
 $maxNum = 1000;

// i just created this function, since we’ll be generating
// # in various sections, and i just want to make sure that
// if we need to change how we generate random #, we don’t 
// have to make multiple changes to the codes everywhere. 
// (basically, to prevent mistakes)

function GenerateRandomNumber($minNum, $maxNum){
   return round(rand($minNum, $maxNum));
}

//generate 49 more random #s to give a total of 50 random #s
for($i = 1; $i <= 49; $i++){
    $num1 = GenerateRandomNumber($minNum, $maxNum);   
        while(in_array($num1, $array)){
            $num1 = GenerateRandomNumber($minNum, $maxNum);
        }   
    $array[$i] = $num1;
}

asort($array); //just want to sort the array

//this simply prints the list of #s in list style
echo '<ol>';
foreach ($array as $var){
    echo '<li>';
    echo $var;
    echo '</li>';
}
echo '</ol>';

答案 3 :(得分:1)

保留您生成的所有先前号码的持久列表(在数据库表或文件中),并检查新生成的号码是否不在列表中。如果您发现这个数字过于昂贵,请在足够数量的位上生成随机数,以保证极低的冲突概率。

您还可以使用增量方法来分配这些数字,例如基于当前时间和random_part的timestamp_part的串联,以确保在多个用户同时上传文件时不会发生冲突。

答案 4 :(得分:1)

您可以使用上面建议的microtime(),然后附加原始文件名的哈希值,以进一步避免在(罕见)完全当代上传的情况下发生冲突。

答案 5 :(得分:1)

您的假设中存在一些缺陷,随机值将是唯一的 - 无论随机数生成器有多好。此外,随机数生成器越好,计算结果所需的时间就越长。

使用数据文件的哈希值不是更好 - 这样您就可以获得检测重复提交的添加好处。

如果检测到重复已知是非问题,那么我仍然建议这种方法,但是根据检测到的冲突修改输出(但使用比计划提供的更便宜的计算方法) Lo'oris)例如

 $candidate_name=generate_hash_of_file($input_file);
 $offset=0;
 while ((file_exists($candidate_name . strrev($offset) && ($offset<50)) {
    $offset++;
 }
 if ($offset<50) {
    rename($input_file, $candidate_name . strrev($offset));
 } else {
    print "Congratulations - you've got the biggest storage network in the world by far!";
 }

这将使您能够使用sha1哈希存储大约25 * 2 ^ 63个文件。

至于如何生成散列,将整个文件读入PHP可能会很慢(特别是如果你尝试将它全部读入一个字符串来散列它)。大多数Linux / Posix / Unix系统都带有像'md5sum'这样的工具,可以非常有效地从流中生成哈希。

℃。

答案 6 :(得分:0)

  1. 伪造文件名
  2. 尝试打开该文件
  3. 如果存在,请转到1
  4. 创建文件

答案 7 :(得分:-1)

使用基于时间戳的东西可能。有关详细信息,请参阅microtime功能。或者uniqid根据当前时间生成唯一ID。

答案 8 :(得分:-1)

保证唯一不能随机。随机不能保证唯一。如果你想要唯一(没有随机),那么只需使用整数:0,1,2,... 1235,1236,1237,......绝对唯一,但不是随机的。

如果这不合适,那么你可以拥有随机的外观。您对整数使用加密使它们看起来是随机的。使用DES将为您提供32位数字,而使用AES将为您提供64位数字。使用任一方法加密0,1,2,...按顺序使用相同的密钥。您需要存储的只是密钥和下一个要加密的号码。由于加密是可逆的,因此加密的数字保证是唯一的。

如果64位或32位数字太大(32位是8位十六进制数字),那么请查看保留加密的格式,这样可以在一定的时间内为您提供更小的尺寸范围。

答案 9 :(得分:-2)

我的解决方案通常是图像内容的哈希(MD5 / SHA1 / ...)。这有一个额外的好处,如果人们上传相同的图像两次,你仍然只有一个图像在硬盘上,节省一些空间(你必须确保如果一个用户删除图像而另一个用户拥有使用中的相同图像。)