PHP机制,以防止用户上传相同的文件两次


PHP mechanism to prevent users from uploading the same file twice

我试图让用户通过PHP网站上传文件。由于所有文件都保存在服务器上的一个文件夹中,因此可以想象(尽管承认可能性很低)两个不同的用户可以上传两个文件,尽管它们不同,但名称完全相同。或者它们完全是同一个文件。

在这两种情况下,我都希望在文件上传后立即使用exec("openssl md5 " . $file['upload']['tmp_name'])来确定文件的MD5哈希值。然后,我将检查数据库中是否有相同的MD5散列,如果找到,我将不完成上传。

然而,在move_uploaded_file文档中,我发现了这个注释:

警告:如果您在数据库中保存md5_file哈希值以保存上传文件的记录,这对于防止用户两次上传相同的文件非常有用,请注意,在使用move_uploaded_file之后,md5_file哈希值会发生变化!当文件被删除时,您无法在数据库中找到相应的哈希值并将其删除。

这是真的吗? tmp目录中文件的MD5散列在将其移动到永久位置后是否会更改?我不明白为什么会这样。不管怎样,有没有其他更好的方法来确保同一个文件不会多次上传到文件系统?

如果你被答案中给出的所有原因所说服,并决定根本不使用md5(我仍然不确定你是否想要或必须使用哈希),你可以为每个用户和每个文件名附加一些唯一的东西。这样,您最终将获得更具可读性的文件名。比如:$filename = "$filename-$user_ip_string-$microtime";。当然,在此之前,您必须准备好所有三个变量并对其进行格式化,这是不言而喻的。

不可能有相同的文件名,相同的IP地址和相同的微时间同时出现,对吗?你可以轻松地利用微时间,但IP将使其更加确定。当然,就像我说过的,如果您决定不使用散列而采用更简单的解决方案,那么所有这些都将失效。

不应该用exec("openssl md5 " . $file['upload']['name']) name代替吗?

看来确实是这样。我也很快浏览了一下文档。但是,为什么不使用move_uploaded_file共享之前的md5校验和,并将该值存储在数据库中,将其直接与新文件链接?也就是说,你可以随时检查上传的文件,以及该文件是否已经存在于你的文件系统中。

这确实需要一个数据库,但大多数人都可以访问数据库。

尝试将上传的文件重命名为唯一的id。使用:

$dest_filename = $filename;
        if (RENAME_FILE) {
      $dest_filename = md5(uniqid(rand(), true)) . '.' . $file_ext;
         }

如果有帮助请告诉我:)

不,通常哈希值不会被move_uploaded_file以某种神奇的方式改变

但是,如果你计算md5()包括文件的路径,哈希值肯定会改变,如果文件被移动到一个新的路径/文件夹。

如果你md5()文件名,什么都不会改变

用唯一的名字重命名上传的文件是个好主意。

但不要忘记找到文件最后存储文件,是在您的vHost的文档根文件夹之外。它位于那里,如果不使用php脚本就无法下载。

最后的注释:虽然这是非常非常不可能的,md5哈希的两个不同的文件可能是相同的