孤陋寡闻,昨天刚知道秒传油猴脚本这个东西,于是结合源码抓包研究了一下。
其基本原理可以用这篇文章嘿嘿,我发现了百度网盘秒传的秘密 - 51CTO.COM的这段话总结:
百度网盘上传时,如果是超过 256KB 的文件,将计算整个文件的 MD5 和文件前 256KB 内容的 MD5 ,并对两个 MD5 值加密后请求后端执行秒传。后端通过两个 MD5 和长度信息判断是否存在该文件,如果存在则完成秒传。
可能文章过时了,我没有发现对两个 MD5 值的加密,但发现了另一个现象,不得要领。描述如下:
百度页面提供的获取文件列表的 xhr 请求中可以看到每个文件的 MD5 (简称 MD5A ), 秒传请求中使用整个文件的 MD5 (简称 MD5B )和前 256KB 内容的 MD5 (简称 MD5C )。我发现有些文件的 MD5A 跟 MD5B 一致,有些文件的则不一致,并且这跟文件大小没有什么关系。MD5A 就是算出来哪个,而 MD5B 是从文件下载请求的响应 headers 中获取的,在 Content-MD5 字段。
所以请问,这个 MD5B 是怎么来的,怎么会跟 MD5A 不一致呢?已经有 MD5C 用来规避 MD5 碰撞了,这种设计又是为了什么?
看到qjfoidnh/BaiduPCS-Go: iikira/BaiduPCS-Go原版基础上集成了分享链接/秒传链接转存功能有关于MD5的叙述,也许MD5A可能是分片上传导致的:
- 分片上传之后, 服务器可能会记录到错误的文件md5, 可使用 fixmd5 命令尝试修复文件的MD5值, 修复md5不一定能成功, 但文件的完整性是没问题的.
- 禁用分片上传可以保证服务器记录到正确的md5.
- 禁用分片上传时只能使用单线程上传, 指定的单个文件上传最大线程数将会无效.
使用分片上传文件, 当文件分片数大于1时, 百度网盘服务端最终计算所得的md5值和本地的不一致, 这可能是百度网盘的bug.
不过把上传的文件下载到本地后,对比md5值是匹配的, 也就是文件在传输中没有发生损坏.
对于MD5值可能有误的文件, 程序会在获取文件的元信息时, 给出MD5值 "可能不正确" 的提示, 表示此文件可以尝试进行MD5值修复.
修复文件MD5不一定能成功, 原因可能是服务器未刷新, 可过几天后再尝试.
修复文件MD5的原理为秒传文件, 即修复文件MD5成功后, 文件的创建日期, 修改日期, fs_id, 版本历史等信息将会被覆盖, 修复的MD5值将覆盖原先的MD5值, 但不影响文件的完整性.
注意: 无法修复 20GB 以上文件的 md5!
1
kiotech 2021-11-26 14:43:26 +08:00
可能是为了优化性能,File Meta 信息生成 MD5 值 A ,文件内容生成 MD5 值 B 。文件内容相同,但修改了文件名称 /日期等 meta ,会导致 MD5 变化。
|
2
JinTianYi456 2021-11-26 15:29:44 +08:00
> 最后给大家留一个思考题:后端拿到 MD5 后,怎么判断后端是否有这个 MD5 呢? 这可是大厂经常爱考的一个面试题哦,来开动脑筋想一下!
怎么搞?有奇淫技巧? |
3
kera0a 2021-11-26 15:42:22 +08:00 via iPhone 2
@JinTianYi456 布隆过滤器
|
4
JinTianYi456 2021-11-26 16:31:10 +08:00
@kera0a #3 感觉好像有点不对,比如后端拿到 md5 了,返回一定存在,那就秒传成功;返回 unknown ,那就开始上传,大不了多存一份呗。但如果是布隆过滤器,返回一定不存在,那就开始上传;返回 unknown ,也得上传啊。
|
5
finab 2021-11-26 17:05:44 +08:00
@JinTianYi456
我没有真的做过类似的东西,我只是简单的考虑哈~ 先走布隆过滤器,返回一定不存在,至少这部分查询就已经确切完成了,不能闪存的文件就可以开始上传了(新文件和个人文件不知道占多少查询比率)查询结束。 已经上传过的文件,可以再查一个缓存,是返回一定存在或 unknown , 可以缓存热门文件之类的。 再之后就是查个人缓存或者查库或者直接传都行,这部分 上传过又不是热门的文件 量 相对来说就很少了。 |
6
selfcreditgiving 2021-11-26 17:47:29 +08:00 1
做过分片上传功能的就知道怎么回事了。一个大文件算 MD5 很慢的,在客户浏览器计算 md5 ,如果是 1G 文件等个 10 秒用户才看到上传进度条开始动,这个不太能接受。百度是文件头尾各取一部分内容合并起来生成“伪文件 md5”(一定程度上可以当做是一个文件的唯一 ID )。
第二个 MD5 是等大文件上传后,在后端再生成的“真文件 MD5”。 |
7
selfcreditgiving 2021-11-26 18:07:48 +08:00
|
8
nowheretoseek OP @selfcreditgiving 有道理,我没相关经验就是参不透。所以 MD5B 即 Content-MD5 字段获取的才是完整文件的 MD5 ,MD5A 是最初上传时在客户端生成的吧
|
9
selfcreditgiving 2021-11-26 22:24:30 +08:00 1
@nowheretoseek
>百度页面提供的获取文件列表的 xhr 请求中可以看到每个文件的 MD5 (简称 MD5A ), 秒传请求中使用整个文件的 >MD5 (简称 MD5B )和前 256KB 内容的 MD5 (简称 MD5C )。 从这句话分析的话,肯定是秒传请求的是 客户端生成的“快速版的 MD5”。获取文件列表请求的 MD5 是真实的 文件全量 MD5 |
10
nowheretoseek OP @selfcreditgiving 我找了个小点的文件验证,发现文件下载时从 headers 中拿到的 MD5B 是全量 MD5 ,文件列表 xhr 请求中给出 MD5A 的不是。Content-MD5 在响应头中,作为真实 MD5 ,供客户端验证下载的文件无误,也是应有之义。
根据你前面的讲解,有无可能 MD5A 是在初次上传时生成,仅作为标识符使用?总之,它在哪个环节、根据什么规则、为了什么而生成,我还是不太清楚。 |
11
nowheretoseek OP @selfcreditgiving 提问时找了几个文件验证,正好 MD5A 与根据文件算出来的 MD5 一致,而 MDB5 要下载抓包才能知道,想当然就认为 MD5A 是全量文件的 MD5 了,已附言更正。抱歉。
|