1. 背景
使用Okhttp的框架,在七牛服务器上进行文件下载,发现一个奇怪的问题,在进行 Http 进行下载的时候,Response 的回包里面,偶尔会出现没有 Content-Length 的情况,导致无法准确的获取下载进度。
在查找问题的过程中,较深入的了解Http下载的流程和fiddler抓包工具的使用,并在与七牛的运维确定问题后,给出了我认为较合理的解决方案。
2. 原因
造成没有 Content-Length 的原因,是由于七牛的服务器没有返回这个字段,七牛方面给出的回复如下:
这边排查当请求头带有 Accept-encoding: gzip 时,第一次请求到某个节点时,会没有 content-length 头,第二次请求到相同节点,就会带这个头了。
当 CDN 节点需要做 gzip 压缩时,为加快第一次响应速度,会在做完 gzip 压缩后直接先响应内容,再计算 content-length ,这样第二次访问到该节点的时候,会把上次的 gzip 压缩内容和 content-length 都返回。
所以原因总结要点如下:
- 七牛服务器默认会对文本格式的文件进行 gzip 压缩,也只有文本格式的文件会出现返回的 Response 里面没有 Content-Length 的问题。(目前与官方确定的是只有文本文件会进行压缩,并不确定是不是其他文件就真的没有)
- 之所以出现有时候有 Content-Length ,有时候没有,是因为数据来源是不同的 CDN 导致的。只有第二次从 CDN 取到相同数据的时候才有 Content-Length ,虽然我们访问的域名没有变,但是数据来源的 CDN 可能变了,所以导致了第二次获取的 Content-Length 还是没有。
3. 解决方式
由于是使用的七牛的存储,不可能要求对方必须返回 Content-Length ,所以我们可以通过下面这些手段来实现进度更新或者规避为空的情况:
必须使用Content-Length(不推荐)
在发送的请求头部,在发送请求时,添加头部 (“Accept-Encoding”,“identity”)