其余日常利用的git在提交文件时也有类似的操作,但用的不是md5而是sha1,打开“.git/objects/ ”目录里面便是sha1算法天生的文件。
sha1和md5的浸染是相同的,但sha1碰撞难度更高,有更好的安全性,但在一样平常情形下,md5就已经够用了。
动手开始写代码,代码运行起来后,碰着了第一个困难,"磁盘占用率太高",记得以前用机器硬盘时,windows动不动就磁盘占用率100%,用了各种办法都没法办理,以为这是微软在提示用户,你的硬盘该当升级了,末了只好升级固态硬盘办理了这个问题,没想到本日又碰着了这个问题。
我用的是php的md5_file()函数打算文件的md5值,当打算2G以上mp4文件的md5值时cpu 内存都正常,磁盘占用却率升到70%以上。于是我改换了编程措辞,看是否还有这个问题。
首页找到了一个python打算文件md5值的封装,但测试下来也是一样的问题,磁盘占用率太高,于是又用上了js,在github找到了spark-md5.js这个库,在浏览器前端打算文件的md5值,创造虽然没有磁盘占用率太高的问题,但浏览器的内存占用又太高了。
于是就想能不能赓续定下文件大小,对太大的文件不打算md5了,结合文件大小,末了修正韶光,创建韶光等成分来做文件的唯一标识(找出文件有多少个副本),这个方法并不好,由于文件的元信息是可以随意改动的,要造出两个元信息完备同等的文件并不困难。
经人指示后,觉得还是要用md5才行,但对付太大的文件,可以并不打算全体文件的md5,而是抽取文件部分内容打算hash。由于并不须要文件的全部内容。
对付太大的文件利用:文件大小+内容
抽样(头、中、尾或每隔xx字节抽样一次哈希),写了一段php代码来验证这一思路,创造可行。测试下来没有磁盘占用率太高的情形,也不吃内存,没有性能问题,
function file_md5_16k($path){ $size=filesize($path);//取得文件大小 if($size>16384){//如果文件大于16kb $str=$size; $str.=file_get_contents($path,null,null,0,4096);#文件头部4kb $str.=file_get_contents($path,null,null,(($size/2)-2048),4096);#文件中部4kb $str.=file_get_contents($path,null,null,($size-4096),4096);#文件尾部4kb return md5($str); }else{ //文件不太,不抽样,直接打算全体文件的hash return md5_file($path); }}
这里只是测试16kb以上的文件就用了抽样打算,实际运用中16k的文件太小了,大于16kb的文件太多,中间修正了一些内容很会产生重复。该当设置的更大一些。
md5存在重复可能,在md5根本上再结合文件类型,文件元信息等就可以对文件做唯一标识,避免文件重复,从而建立文件指纹库。
当然要实现文件“秒传”要做的远远不止这些,这个只是实现事理算法。
末了感谢emacs-china论坛的的热心用户 @twlz0ne @Liutos @SuperMMX 给予的指示。