创建独特的图像名称

5

如何为用户上传的图像创建唯一的名称?

我不想有任何重复,因此类似于MD5($filename)的方法不适用。

有什么好的建议吗?


有没有一种方法可以从1、2、3等开始给出唯一的数字系列,就像数据库中给出主键一样? - Faizan
15个回答

15

正如之前提到的,我认为创建唯一文件名的最佳方式是简单地添加time()。就像这样:

$image_name = time()."_".$image_name;

如果连续执行两次,这可能会导致名称冲突,因为time()对于两者都是相同的。可以使用下面答案中建议的microtime()来避免这种情况。 - Sami El Maameri
如果一个用户同时上传多张具有相同名称的图片,那么这将不好。 - nafischonchol

8
从上传文件中提取文件扩展名:
$ext = pathinfo($uploaded_filename, PATHINFO_EXTENSION);

精确到秒的时间获取:time()

获取一些随机数:md5(microtime())

将时间转换为36进制:base_convert (time(), 10, 36) - 36进制可以将一个10字节的字符串压缩到约6字节,以便更多地使用随机字符串

将所有内容发送出去作为16个字符的字符串:

$unique_id = substr( base_convert( time(), 10, 36 ) . md5( microtime() ), 0, 16 ) . $ext;

我认为那不太可能发生冲突 - 如果您不介意文件名很长,甚至可以不截断它。


1
你忘记在唯一标识符和扩展名之间加上点了。 - mombul

4
如果你确实需要一个文件名(从你的问题中并不完全清楚),我建议使用tempnam(),它可以创建一个具有唯一文件名的文件,并将访问权限设置为0600,放在指定的目录中。让PHP来处理独特性的工作。请注意,tempnam()不仅返回文件名,而且实际上还创建了文件;当你放置图像文件时,你可以直接覆盖它。

我认为这个答案非常有用但是被低估了。但是,当你的存储在服务器外部,比如对象存储(S3、云文件等),你就可以依赖它了 :( - lcjury

2

您可以对图像数据本身进行哈希处理(例如md5,sha)。这有助于识别重复图像(如果它们是逐字节相同的)。但是,任何足够长的随机字符字符串都可以使用。

您始终可以通过某种方式操纵文件名,使其看起来像:

/image/0/1/012345678/original-name.jpg

这样文件名看起来很正常,但仍然是唯一的。


1
我建议使用sha1_file()而不是md5_file()。它更不容易发生碰撞。 你也可以使用hash_file('sha256', $filePath)来获得更好的结果。

2
更少的碰撞?让我们来看一下更广阔的视角。使用MD5,并考虑生日悖论,您发生碰撞的几率小于0.000000000000000000000000000000000000000000000000001%。 - Synchro

0

哈哈,MD5算法可以产生大约63340000000000000000000000000000000000000000000000种可能性。此外,为了保险起见,您还可以使用它。

$newfilename = md5(time().'image');
if(file_exists('./images/'.$newfilename)){
    $newfilename = md5(time().$newfilename);
}
//uploadimage

相同的输入会产生相同的哈希输出。因此,如果问题在于输入不唯一(文件名),那么输出也不会是唯一的。 - Matthew

0

对于短名称:

$i = 0;
while(file_exists($name . '_' . $i)){
  $i++;
}

警告:如果两个用户同时上传具有相同名称的图像,则在多线程服务器上可能会失败。在这种情况下,您应该包括用户名的md5。


0

两个用户在同一微秒上传具有相同名称的图像的概率有多大?

尝试

    $currTime = microtime(true);
    $finalFileName = cleanTheInput($fileName)."_".$currTime;

// you can also append a _.rand(0,1000) in the end to have more foolproof name collision

    function cleanTheInput($input)
    {
     // do some formatting here ...
    }

这也有助于您跟踪文件上传时间以进行分析,或者可能对文件进行排序、管理。


0

0

为了获得良好的性能和独特性,您可以采用以下方法:

  • 文件将存储在服务器上,名称类似于md5_file($file).jpg

  • 定义存储文件的目录是通过剥离第一个字符(第一级)和第二个字符(第二级)来从MD5文件名中确定的,例如:

    uploaded_files\30\c5\30c567139b64ee14c80cc5f5006d8081.pdf

  • 在数据库中创建记录,包括文件ID、原始文件名、上传用户ID以及文件在服务器上的路径。

  • 在服务器端创建脚本,用于提供下载角色 - 它将从数据库中按ID获取文件,并输出其内容以及用户提供的原始文件名(参见CodeIgniter download_helper的PHP示例)。因此,文件的URL将如下所示:

    http://site.com/download.php?file=id


优点:

  • 压缩冲突威胁

  • 在文件查找方面表现良好(一个目录中没有太多文件,在同一级别上没有太多目录)

  • 原始文件名被保存

  • 您可以通过服务器端脚本(检查会话或cookie)调整对文件的访问权限

缺点:

  • 适用于小文件大小,因为在用户下载文件之前,服务器必须将此文件读入内存

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