记录一次压缩包修复经历
逆天百度云,逆天7zip

事故场景

在百度云上下了个30多G的7z压缩包,断断续续下了好几天(应该是3到4天吧,反正就那100多K的速度一直挂着),好不容易下完了,结果发现解压到一半就报错了。

Data Error in encrypted file. Wrong password?

当时看到这个错误其实能猜到大致的原因了,小概率是网络传输出了问题,大概率是因为自己当时桌面崩了只能强制关机导致的文件损坏。

解决思路

解决还是很简单的嘛,只要找到报出这个错误时7z文件在读什么位置,把那个位置的文件重下一遍就好了。 但是,7z的verbose output非常的不verbose,基本上看不到啥特别底层信息。加了个-bb3就多输出了一个文件名。l -slt也只能看到解压前的元信息。 我还试了换成windows的gui版本,结果也是一样的,看到不出错的位置,只能知道大概是解压到30%多左右的时候出错了。

中途我还想过写个脚本通过stdin把数据传给7z,结果一搜才知道7z的LZMA2格式根本不支持流式输入,强行-so直接Not Implemented Error

实在没辙了,最后只能用万能的strace了:

strace -f -e trace=openat,read,pread64,lseek,close 7z t xxx.7z &> ./7zip.log

然后果然就在log里找到了错误位置:

[pid 3105169] read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 524288) = 524288

这是log中的最后一次读操作,读到了一长串0,然后就报错了,很显然就错在这个位置了,刚分配了空间,但由于电脑强制关机,数据没写进去,所以全是0。 正常思路就是往上回溯到最近的lseek然后数offset就能找到具体位置了,但这一大串的0太有标识性了所以直接搜就行了。

grep -aboP '\x00{100,}' xxx.7z

拿到了起始位置之后用二分法大致确认了一下范围是在9927917560-9932117560之间,接下来把这个范围的文件内容重新下载一下就行了。

可要怎么下载这部分文件呢?考虑到之前也用过一些百度云的直链脚本,我有理由相信百度云这种国民级别的网盘APP,它的API肯定有人已经研究过了,因此一通搜索之下很快我就找到了这个项目 按照README初始化配置后,我成功地通过BaiduPCS-GO locate xxx.7z拿到了直链。

万幸这百度云虽然在速度上不当人,但在断点续传这方面用的还是标准的HTTP Range请求,所以也不用写啥特殊的工具, 直接扔给aria2c,加上--header 'User-Agent: netdisk;P2SP;3.0.0.8;netdisk;11.12.3;ANG-AN00;android-android;10.0;JSbridge4.4.0;jointBridge;1.1.0;', --header="Range: bytes=9927917560-9932117560"就能下这个文件了。 不过aria2c不知道为什么还是创建了一个30多G的文件,不过无所谓,前面的数据是对的就行。 最后就是一个dd命令把数据写回去就行了:

dd if=f752b08c1qfd5f6cbf43fc943444a05a of=xxx.7z bs=1 seek=9927917560 count=4200000 conv=notrunc

不得不吐槽这bs只能设置成1是真难受,不知道有没有啥更优雅的方法,不过反正也说不上特别慢,1分钟不到就写完了。

如此成功解压,问题圆满告一段落,めでたしめでたし✧◝(⁰▿⁰)◜✧

事后吐槽

虽然我承认是我自己我误操作导致的文件损坏,但百度云你真就一点责任都没有吗,明明自己就存着文件的哈希值,下载完之后就不能顺便校验一下吗? 就这么信任用户下载到一半的文件是完整的吗?太不靠谱了吧。

另外那个分享资源的人也是挺NB的,上传一个30多G的压缩包,分卷都不带分的,还是太相信自己的网络质量了。 果然互联网资源分享还得是rar啊,恢复记录对于大文件的网络传输实在是太有用了,虽然我互联网仓鼠那么多年,确实没几次用到过这个压缩包修复功能,但每次都能省下一大笔时间。 你7z固然压缩率高,但对于视频图片这类扛压缩的资源根本就压不动,提高压缩等级就是纯折磨自己也折磨解压的人。


最后修改于 2025-12-20