百度网盘如何大文件实现秒传? |
您所在的位置:网站首页 › 百度秒传怎么使用 › 百度网盘如何大文件实现秒传? |
百度⽹盘如何⼤⽂件实现秒传? 百度⽹盘上传时,如果是超过 256KB 的⽂件,将计算整个⽂件的 MD5 和⽂件前 256KB 内容的 MD5 ,并对两个 MD5 值加密后请求后端执⾏秒传。后端通过两个 MD5 和长度信息判断是否存 在该⽂件,如果存在则完成秒传。 有个读者在微信上问我:百度⽹盘的秒传功能是如何实现的 ? 这个问题我其实有想过,我猜测⼤概是前端计算⼀个⽂件的哈希值 ( ⽐如 MD5) 发送给后端,⽹盘服务器判断是否存在这个⽂件,如果存在就直接在后端完成⽂件的 “ 转存 ” ,直接告诉前端: 上传成功。 不过这是我⾃⼰猜测的,到底对不对,⼀直也没有去验证过。 我把我的猜测告诉了他,结果他问了⼀句:如果发⽣哈希冲突了怎么办呢 ? 。 我想了⼀下⼜说:那就多加⼏个哈希 ! 不过百度⽹盘到底是怎么做的呢 ? 这位读者既然问到了,我就趁机花了⼏分钟研究了⼀下,算是解答了这个疑惑,增加了知识。 MD5 冲突 ⾸先,只⽤⼀个哈希值,已经有事实证明是会发⽣冲突的,⽽不只是理论上。 ⽐如我在知乎上找到了⼀个例⼦,下⾯两段不同的数据,只相差两个字节: 分别计算 md5 ,结果是⼀样的: 所以,如果只⽤⼀个哈希值就判定是同⼀个⽂件,那就⽐较容易会出现张冠李戴的情况。 甚⾄,有⼈还基于此提出⼀种哈希碰撞攻击:如果我知道⼀个⽂件的 md5 值,但拿不到这个⽂件,我通过数学计算,构造⼀个相同 md5 的⽂件,那岂不是就把那个⽂件直接给我转存过来 了 ? 如果是⼀个私密的⽂件呢 ? 那不出事了 ! 百度⽹盘的做法 那百度⽹盘是咋做的呢 ? ⾸先上传⼀个稍微⼤⼀点的⽂件 ( ⼩⽂件有计算哈希的功夫早就传完了 ) ,使⽤浏览器 F12 ⼤法,看⼀下它的⽹络请求: 可以看到,百度⽹盘对⽂件进⾏了分块传输,这也是⽬前业界⽐较流⾏的做法,对⼤⽂件进⾏分块,如果⽹络不好断开了,下次只需要传输剩下的分块就⾏了,做到了断点续传。 不过注意看,在上⾯分块的中间,插⼊了⼀个叫 rapidupload 接⼝的请求,从名字你也可以猜出来了,这个接⼝肯定跟它的 “ 秒传 ” 功能有关系 来看⼀下请求的参数,是⼀个 Form 表单,有这么⼏个字段: content-length: ⽂件长度 content-md5: ⽂件的 MD5 slice-md5: ⽂件切⽚的 MD5 看到这⾥你估计猜到了,肯定是这三个参数联合判断,同时满⾜条件才算是同⼀个⽂件 ! 来看下服务器响应了什么: 秒传成功了 ! 那如果上传⼀个后端肯定不存在的⽂件会是返回什么呢 ? 我构造了⼀个做测试: 看到了吧, 404! 说明后端没这个⽂件,那就⽼⽼实实传吧 ! 接着,我想看⼀下这个切⽚ md5 ,百度⽹盘是怎么在切的。 通过⽹络通信中的 Initiator 功能,可以定位到是哪⾥的 JS 代码在发⽣请求: 通过调⽤堆栈,看到了叫 rapidUpload 这个函数,再上下⼀跟进,找到了这个切⽚ MD5 计算的地⽅: 其实就是对⽂件的前 262144 个字节,也就是 256KB 进⾏计算。如果⽂件⽐这还⼩,那就⽤不着秒传了。 但奇怪的是,我扣取了⽂件的前 256 个字节,计算出来的 md5 ,和它接⼝中上传的参数并不⼀致 ! 这让我疑惑了好⼏分钟,难道事情没这么简单 ? 我⼜打了断点在计算的位置,发现它计算的跟我计算的⼜是⼀样的,但通过⽹络发出去以后就变了,真是薛定谔的 MD5 ,奇怪了 ! 不过,程序不是量⼦⼒学,它不会骗⼈,很快我就找到了问题所在:百度⽹盘可能担⼼⾃⼰的路数被发现,对⽂件的 MD5 和切⽚ MD5 都进⾏了加密 ! 这就是加密函数: ⼀些简单的字符串处理⽽已。 好了,现在可以回答前⾯读者的问题了: 百度⽹盘上传时,如果是超过 256KB 的⽂件,将计算整个⽂件的 MD5 和⽂件前 256KB 内容的 MD5 ,并对两个 MD5 值加密后请求后端执⾏秒传。后端通过两个 MD5 和长度信息判断是否存 在该⽂件,如果存在则完成秒传。 这样做,虽然理论上也不能保证不会发⽣哈希碰撞,但通过这种⽅式,⾄少将概率降低了许多。 最后给⼤家留⼀个思考题:后端拿到 MD5 后,怎么判断后端是否有这个 MD5 呢 ? 这可是⼤⼚经常爱考的⼀个⾯试题哦,来开动脑筋想⼀下 !
|
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |