some deep research on wechat downloading files

发布于 2019-10-02  1736 次阅读


background

最近在微信群里发了一个excel表文件,让其他人填好私信发给我。接收两个文件后同步到电脑上,下载时意外发现其中一个文件被另一个覆盖了!其实之前也发现过类似的情况,未深究,故这次打算仔细研究一番其中的原因(程序员的bug).

tests

1.单独在电脑上进行测试,在桌面下新建"trick.docx"文件发送给一个/两个好友,好友用手机接收后再各自发回来,重复多次。

结果:

一个:发回的trick.docx点击变成了trick(1).docx(显示文件名仍然是trick.docx),再转发trick(1).docx(注意这里是转发)发送文件名变成了trick(1)(1).docx;若再发送一次trick.docx,发送出的文件名显示为trick(2).docx.
两个:按好友的发回时间先后,先发回的为trick(1).docx,后发回的为trick(2).docx. (这里对微信文件下载路径做了一些处理,使得路径下仅有发送时的trick.docx.)
还有一种方法:将好友们拉入一个群聊,发文件到群聊下,让好友各自将内容修改后传回群上。结果是先发的实际文件名变成trick(1).docx,后发的实际文件名变成trick(2).docx.

结论:

在电脑上操作,任何时候发送文件/接收文件时都会自动在微信文件下载路径(常量,以下简称下载路径)下保存一份备份,当出现重名时就会触发重命名,具体命名方法为:X.docx重命名为X(1).docx,若存在=>重命名为X(2).docx,若存在继续循环=>...
当然,这里的重命名仅表现在下载路径中,聊天窗口中显示的接收文件名不变。
因此,如果仅在电脑端操作,接收文件出现覆盖现象基本不会发生(因为电脑版每次都会自动检查)。

2.A,B只使用手机,在电脑上事先给A,B发送内容为"A","B"的trick.docx,然后A发送(转发)trick.docx给B.

结果:

B收到的两个文件均显示trick.docx,但点击进入内容不一样,未出现覆盖现象;A转发的也是trick.docx.

结论:

如果仅在手机端操作,手机端不会像电脑端一样显式为文件名重名,但实际文件名不一致(以下用表文件名/实际文件名区别);转发时仅使用表文件名。
推测微信实际文件名存储方式与电脑端一致,但表文件名显示略有区别,故在手机同步到电脑的过程中可能会出现覆盖错误。

3.在电脑上事先给A,B发送内容为"A","B"的trick.docx,然后删除本地备份的trick.docx,退出电脑端,A,B用手机分别转发文件给主机(前面的发送者),重新登录电脑端,接收文件。

这实际上模拟了背景的情景。

结果:

第一个("A")接收到的文件实际文件名为trick.docx,第二个("B")实际文件名也为trick.docx,文件内容为"A",表明B文件被覆盖了。这里第一个、第二个为点开对话框的顺序。注意两者表文件名均为trick.docx.重复测验,交换第一个接收文件的顺序,被覆盖的文件也相应反了过来。一个细节是,被覆盖的文件虽然可以打开,但转发时显示"不能转发未下载的文件/超大文件",即微信仍认为该文件(小文件)未被下载。

4.与3类似,只不过不删除本地备份的trick.docx,其内容更改为"X".

同样是背景的模拟,区别在于后者在电脑端上传了文件,前者在手机端上传(电脑本地无备份)。

结果:

第一个("A")实际文件名为trick(1).docx,第二个("B")实际文件名也为trick(1).docx,表文件名均为trick.docx,文件内容均为"A",表明B被覆盖;交换顺序也会交换覆盖顺序;原文件trick.docx仍存在,内容也未改变.

追加测试:删除trick(1).docx,再次点击微信框B文件,显示了下载条,下载后进入内容为"B",而点击微信框A文件也会进入trick(1).docx,内容为"A";再删除trick(1).docx,点击A,B文件均显示“已被清理”;将删除的trick(1).docx还原回下载路径,点击A,B文件均能打开trick(1).docx,内容为还原的docx里的内容.

结论(3,4):

微信手机同步到电脑时,电脑端仅判断新出现的文件名是否在下载路径存在,若存在则不下载它直接打开,否则下载它后打开。也就是说,同步后的新文件跳过了重名检查,仅在打开操作时进行判断。
同时可发现,微信的“已被清理”仅表示文件在下载一次后不在下载路径存在,其实质仍为对打开操作的响应,故还原后文件又能打开了,而不是“再次下载”。
关于测试4没有覆盖trick.docx的原因,推测同步文件与原有文件属于不同类型,第一个文件采用了与重名检查类似的命名法,而“跳过重名检查”的步骤仅在两同步文件之间发生。

5.与3类似,但事先将A,B,C,主机拉入一个群聊,A,B,C直接上传到群聊,电脑端trick文件事先删除.

结果:

按时间顺序先后,表文件名均为trick.docx,实际文件名依次为trick.docx,trick(1).docx,trick(2).docx,无覆盖现象.

6.类似4+5,电脑端trick文件事先不删除.

结果:

按时间顺序先后,表文件名均为trick.docx,实际文件名依次为trick(1).docx,trick(1)(1).docx,trick(1)(2).docx,无覆盖现象.

结论(5,6):

同一群聊下文件的命名规律难以解释,但可以确定的一点是同一群聊下下载的文件不会出现覆盖现象。

7.设置群聊1,群聊2,成员均为A,B,C,主机,每个群聊操作和5完全一致;登录电脑端后先进入群聊1,再进入群聊2.

结果:

群聊1结果与5一致;群聊2所有文件的实际文件名均为trick.docx,表明其未被下载.

8.设置群聊1,群聊2,成员均为A,B,C,主机,每个群聊操作和6完全一致;登录电脑端后先进入群聊1,再进入群聊2.

结果:

群聊1结果与6一致;群聊2所有文件的实际文件名均为trick(1).docx,表明其未被下载.

结论(7,8):

微信可能使用了偷懒的机制,同步后仅更新第一个需要下载文件的群聊(第一个点入的,一般是最新的)并保证其中所有文件不重名,但对其他群聊的同步文件采用跳过重名检查的方式,具体规则与4结论一致.

summary

单独使用微信电脑版或手机版一般不会出现问题。
同步文件时,微信使用lazy机制,仅更新第一个点入的群聊的所有文件,保证其中文件不重名,以在表文件名后面加若干括号的方式重命名;对其他群聊的同步文件标记lazy,当点击时才开始判断,若实际文件名与原有文件冲突,则按照加括号的方式修改实际文件名;若与同步文件冲突,则不下载并直接打开。
这种lazy机制避免了大多数文件覆盖问题,因为起统计作用的文件很少同时上传到多个群聊,一般是一个群聊,而需要在多个群转发的通知性文件其内容一般是一致的(如果有修改文件名也很有可能加上了括号).
但如果通知性文件的文件名没有修改,内容有变化,就很可能出现不同人接收到的内容不一致的情况。
总结就是:微信垃圾,QQ文明


WRYYYYYYYYY!