比较文件和/或目录的最佳方法是什么。假设我想将文件存储在服务器或集合服务器上,例如基于云的系统。在很多情况下,我的用户彼此合作,而有些则没有。无论哪种方式,我都可以使用相同的文件拥有超过一百人或更多。只有关键的区别是他们喜欢重命名文件或其他什么。但基本上相同的确切数据。现在其他的事情是没有特定的文件类型。有pdf,doc,docx,txt,视频,音频文件等。但问题归结为相同的文件一遍又一遍。我想做的就是把它砍掉。删除数百个欺骗并在数据库存储的帮助下,例如用户提供的文件名,这样我就可以将单个文件保存在我想要的方式和位置,同时仍然提供他们使用的信息。
现在我知道我可以用md5或sha1或sha2或类似的东西做一些基本上给我一个我可用于这种比较的唯一值。但我不确定如何或从哪里开始。比如用php如何获取文件的sha或md5?当我查找那些我获取字符串但不是文件的方法的东西时。
总的来说,我在这里想要反思这些想法,而不是直接的手段......任何帮助都会很棒。
答案 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)
上传文件时:
请求文件时:
答案 2 :(得分:1)
要在$path
...
$hash = md5(file_get_contents($path));
希望这能部分回答你的问题。
答案 3 :(得分:1)
您可以使用:
md5(file_get_contents($filename));
为文件生成哈希。
考虑到这一点,两个完全不同的文件将产生完全相同的md5哈希(与其他哈希相同的问题,尽管通过使用比md5更好的哈希方法可以减少更少的冲突)。要比较两个文件,你需要逐个字节地进行比较,但是你不想分析硬盘上每个文件的每个字节来找到匹配。
您需要做的是将数据库中每个文件的哈希值存储在一列中,该列也应该是索引。
然后,您可以从数据库中选择与新文件具有相同哈希值的所有文件。 这将为您提供一个小文件列表。假设光盘上有100,000个文件。您可能会获得与哈希匹配的几个文件的列表。大多数情况下,列表会很短。然后你可以逐字循环遍历这些文件,看看它是否匹配。搜索具有相同散列的~10个文件的列表将使您无法搜索所有100,000个文件,但仍需要逐字节进行比较,因为这10个文件可能都非常不同。
答案 4 :(得分: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 }}在数据库中是唯一的)
当用户存储文件时,处理该文件(在步骤 1 中描述)并正确保存。为避免服务器上的同一文件夹中包含太多文件,您可以分解uniq_id
并将每个文件分成files.uniq_id
个子文件夹。
接下来,关联yyyy/MM
和user_files.file_id = files.id
并将user_files.user_id = users.id
设置为上传的文件名(请参阅下一步)。
如果用户上传其他文件,请按 2 中的方式处理结果,但请检查结果是否与其他user_files.filename
,files.sha_hash
匹配。此时,如果我们有匹配项,那么文件的名称无关紧要,它很可能是完全相同的文件,因此关联找到的files.md5_hash
和user_files.file_id = files.id
并设置{{1} }上传的文件名。
注意:这会导致您的服务器上有user_files.user_id = users.id
个物理文件和user_files.filename
个虚拟文件。
如果用户在不修改文件的情况下重命名文件,只需重命名与他/她想要重命名的文件匹配的1
。
如果用户删除文件,请检查2
匹配的数量,并且仅在找到user_files.filename
匹配时,删除物理文件和user_files.file_id
条目。否则,只需删除1
关联。
如果用户在重命名或未重命名的情况下修改文件,请执行删除(步骤 5 )和另一次保存(步骤 3 )
答案 5 :(得分:-3)