百度网盘文件上传小探究

先说总结:某些资源搁浅在网盘上理论上是救不了的了,感觉写后台的好兄弟应该是有认真考虑过这个问题的。要么老老实实多备个硬盘,要么就加密上传。

一切的一切首先要从网盘的“急速秒传”功能说起。

为了复现,这里首先把本地上一些被和谐的电影用秒传的方式上传到网盘,就直接用我之前写的一套代码:

“急速秒传”它具体工作原理是啥?很简单,它使用的就4个参数:网盘的文件路径,文件的md5,文件大小(字节数),前256KB内容的md5(这些参数随便抓个包都能get到),网盘服务器根据后面3个参数去自己的存储池查找有没有符合这要求的文件,就一个select的事情,如果有,那就在你指定的文件路径创建一个“文件”,而这个“文件”实际上是以文件ID(百度网盘使用的是FS_ID)的形式链接到自己的网盘路径的,相当于linux文件系统上的一个文件链接而已,毕竟网盘内部存储系统又不需要再复制多一份相同的内容坑自己空间。

上图的bdpan://协议是某个(现在应该已经凉的透彻的)软件使用的秒传协议,内容就是base64编码过的上面这4个参数而已。上传好之后就可以打开网盘客户端下回来:

Oops,惊不惊喜意不意外?

那么,现在是时候思考有什么抢救的措施了,比如通过操作网盘上的数据给它洗个白。

Have a try,先将文件按4MB大小切成若干个小文件块(至于为啥这么做嘛,网盘上传的时候是以4MB作为每个文件块block的默认大小,这里就不动它了)。首先需要考虑的是百度网盘是否具有匹配和谐文件的每个文件块的能力,也就是说和谐了一个大文件,组成它的各个文件块是否也会有影响。

如上图所示,网盘文件的分段上传主要分为三步:通过预创建获取一个上传ID,然后进行分段上传(每段4MB大小)获取每段的MD5,最后再调个API将若干分段的数据合并生成最终的文件。这里选了文件的前8MB分成两段上传,然后再下载回来,整个过程是ok的,说明小文件块是不会收到影响的。不错,可以继续进行下一步探究了。

怎么防范,首先想到的是文件的拼接,也就是将需要抢救的文件和其他什么文件拼在一块组成新的文件,把这新的文件下下来,再把自己手动凑数的那部分数据扔掉就能还原原文件了。为了确保它确实存在网盘上,这里继续先用秒传测试一下网盘里面是否已经有这样的文件了:

如上图所示,前面两个是有的,最后一个由于没上传过,因此秒传就报错了。于是直接跳过第二步分段上传的环节,先预创建拿到上传ID之后直接把MD5扔上去创建最终文件,因为不同分段的MD5是已知的。

当然,想法是完美的,然而实际上就死在最后一步上了:

报了个之前都没出现过的errno,不对劲。

纳闷了,那先试试跳过上传环节先只传一个分段?结果是出乎意外的可行:

我人傻了。不过也没震惊到哪里,用这种方法不分段(也就是只分1段)上传大的文件也是可以的,比起秒传少了个前256KB内容的md5这个参数,以后可以合理利用一下。通过这种方法传上去的整个文件依然是下不了的,这点倒是在我意料之中了。

其实几张图对比可以发现,单分段上传拿到的上传ID是N1-开头的,多分段的是P1-开头的。后面自己抓了一下百度网盘客户端的包,发现它们确实是要么秒传,要么就把整个文件完完整整上传一遍。网盘客户端文件上传的暂停和续传是建立在预创建阶段的,首次上传的时候通过预创建拿到上传ID,接着就进行分段上传,上传过程是可以暂停的,续传的时候需要再次发送预创建请求,并附上上一次的上传ID,这时候已经上传完的分段就不需要再次上传了,当然,整个文件还是得完完整整传一遍的。

最后的结论嘛……搁浅在网盘上的资源是拯救不了的了,所有操作都是建立在本地拥有这资源的一份副本的基础上才能进行的。这也证实了之前写的一套加密备份方案还算是比较有远见的。