唯一标识服务器上的文件和目录以进行比较

时间:2011-08-13 01:38:18

标签: php

比较文件和/或目录的最佳方法是什么。假设我想将文件存储在服务器或集合服务器上,例如基于云的系统。在很多情况下,我的用户彼此合作,而有些则没有。无论哪种方式,我都可以使用相同的文件拥有超过一百人或更多。只有关键的区别是他们喜欢重命名文件或其他什么。但基本上相同的确切数据。现在其他的事情是没有特定的文件类型。有pdf,doc,docx,txt,视频,音频文件等。但问题归结为相同的文件一遍又一遍。我想做的就是把它砍掉。删除数百个欺骗并在数据库存储的帮助下,例如用户提供的文件名,这样我就可以将单个文件保存在我想要的方式和位置,同时仍然提供他们使用的信息。

现在我知道我可以用md5或sha1或sha2或类似的东西做一些基本上给我一个我可用于这种比较的唯一值。但我不确定如何或从哪里开始。比如用php如何获取文件的sha或md5?当我查找那些我获取字符串但不是文件的方法的东西时。

总的来说,我在这里想要反思这些想法,而不是直接的手段......任何帮助都会很棒。

6 个答案:

答案 0 :(得分:3)

$filePath = '/var/www/site/public/uploads/foo.txt'
$data = file_get_contents($filePath); 

$key = sha1($data);   //or     $key = sha1_file($filePath);

将此$ key保存在表的列中,并将该列标记为UNIQUE,因此默认情况下不能存储相同的文件。

使用sha1而不是md5,因为像git这样的许多版本控制系统使用sha1 hash本身来识别文件的唯一性

答案 1 :(得分:2)

上传文件时:

  • 计算哈希值(SHA1等)
  • 将文件重命名为该哈希并存储它(除非已存在具有该哈希的文件[您已经拥有它])
  • 将哈希值存储在数据库中。

请求文件时:

  • 从数据库中获取哈希
  • 根据哈希值
  • 返回文件
  • 使用HTTP标头,以便用户的浏览器使用他们使用的文件名向他们提供

答案 2 :(得分:1)

要在$path ...

获取文件的md5哈希值
$hash = md5(file_get_contents($path));

希望这能部分回答你的问题。

答案 3 :(得分:1)

您可以使用:

md5(file_get_contents($filename));

为文件生成哈希。

考虑到这一点,两个完全不同的文件将产生完全相同的md5哈希(与其他哈希相同的问题,尽管通过使用比md5更好的哈希方法可以减少更少的冲突)。要比较两个文件,你需要逐个字节地进行比较,但是你不想分析硬盘上每个文件的每个字节来找到匹配。

您需要做的是将数据库中每个文件的哈希值存储在一列中,该列也应该是索引。

然后,您可以从数据库中选择与新文件具有相同哈希值的所有文件。 这将为您提供一个小文件列表。假设光盘上有100,000个文件。您可能会获得与哈希匹配的几个文件的列表。大多数情况下,列表会很短。然后你可以逐字循环遍历这些文件,看看它是否匹配。搜索具有相同散列的~10个文件的列表将使您无法搜索所有100,000个文件,但仍需要逐字节进行比较,因为这10个文件可能都非常不同。

答案 4 :(得分:1)

您可以通过多种方式完成此类系统。但是,如果我必须从头开始编写一个,我很可能会这样做:

  1. 有三个数据库表(伪代码):

    table users {
       id integer         ## PK
       username string
       password string    ## sha1
       ...
    }
    
    table user_files {
       user_id integer    ## Composite INDEX
       file_id integer    ## 
       filename string
    }
    
    table files {
       id integer           ## PK
       uniq_id string       ## basically 'yyyMMddhhmmssRRRR' INDEX
       sha_hash string      ## sha1
       md5_hash string      ## md5
    }
    

    如果files.sha_hash是计算文件sha1的结果,files.md5_hash是计算同一文件的md5的结果,如双重安全检查,和files.filename实际的文件名。在服务器上,文件将被存储并重命名为files.uniq_id以确保没有名称冲突,其中最后RRRR个字符表示随机字符串(周期RRRR直到{{1 }}在数据库中是唯一的)

    注意:PHP提供sha1_filemd5_file。在计算文件时使用这些文件!

  2. 当用户存储文件时,处理该文件(在步骤 1 中描述)并正确保存。为避免服务器上的同一文件夹中包含太多文件,您可以分解uniq_id并将每个文件分成files.uniq_id个子文件夹。

    接下来,关联yyyy/MMuser_files.file_id = files.id并将user_files.user_id = users.id设置为上传的文件名(请参阅下一步)。

  3. 如果用户上传其他文件,请按 2 中的方式处理结果,但请检查结果是否与其他user_files.filenamefiles.sha_hash匹配。此时,如果我们有匹配项,那么文件的名称无关紧要,它很可能是完全相同的文件,因此关联找到的files.md5_hashuser_files.file_id = files.id并设置{{1} }上传的文件名。

    注意:这会导致您的服务器上有user_files.user_id = users.id个物理文件和user_files.filename个虚拟文件。

  4. 如果用户在不修改文件的情况下重命名文件,只需重命名与他/她想要重命名的文件匹配的1

  5. 如果用户删除文件,请检查2匹配的数量,并且仅在找到user_files.filename匹配时,删除物理文件和user_files.file_id条目。否则,只需删除1关联。

  6. 如果用户在重命名或未重命名的情况下修改文件,请执行删除(步骤 5 )和另一次保存(步骤 3

答案 5 :(得分:-3)

  1. 有必要吗?硬盘现在非常便宜,所以谁在乎重复?我想这不是那么大吗?
  2. MD5等。不是唯一的。只是快速说两个文件不一样。两个文件可能具有相同的MD5值但包含不同的数据。