初以为,下载是个极其简单的东西,想试一下。因为知道某些app的下载失败率很高,所以搞了个小聪明讨个巧,分块下载,每块一个md5,如果分块校验失败,则对本块重新下载(貌似古时候的FlashGet就是这么搞的)。
模块
理想情况下,还是分层的:
- 对外接口:为使用下载功能暴露的接口,启停、取消之类的
- 系统接口:监听系统事件控制下载过程
- 下载:执行下载的部分
- 日志:记录下载的状态,保证下载可以在中断后恢复
- 存储:对于小文件,听说使用SQLite+一个大文件来存储,要优于直接使用FAT32
其实是个很简单的系统,苦功夫比较多,做的也比较烦躁。记录下细节吧:
HTTP
这部分基本是抄的Android的DownloadManager,附带着看了一下HTTP请求和返回的一些东西
请求Header:
- ETag:相对于服务端定义的,该请求的签名,由第一次请求返回,用来标识数据是否变化。请求时,key是If-Match
- Range:请求要求的数据范围,这个是多线程下载和断点续传的重点。每次下载一段,续传/多线程都只下载目标文件的一部分
- Referer:该请求的来源
- Connection:是否复用链接,close时为不复用。DownloadManager为了维护网速和流量控制,设置为close
- Accept-Encoding:压缩类型,为了断点续传,设为identity
应答Header:
- Content-Range:对应的正则是bytes\s{1,}(\d{1,})-(\d{1,})/(\d{1,})。三个group分别是起始、终止和总比特数
- ETag:etag字符串
网络状况
- 监听:android.net.conn.CONNECTIVITY_CHANGE
- 获取:ConnectivityManager.getActiveNetworkInfo()获取NetworkInfo
- getType/getSubType:汇总的列表