iOS开发网络篇之文件下载、大文件下载、断点下载

525 查看

这里写图片描述

iOS开发中经常会用到文件的下载与上传功能,今天咱们来分享一下文件下载的思路。文件上传下篇再说。

文件下载分为小文件下载与大文件下载

小文件下载

小文件可以是一张图片,或者一个文件,这里指在现行的网络状况下基本上不需要等待很久就能下载好的文件。这里以picjumbo里的一张图片为例子。

NSData方式

其实我们经常用的 [NSData dataWithContentsOfURL] 就是一种文件下载方式,猜测这里面应该是发送了Get请求。

当然下载代码应该放到子线程执行

NSURLConnection方式下载

就是发送一个异步的Get请求,回调的data就是我们下载到的图片。这些都很简单,今天主要说的是大文件的下载。

大文件下载

NSURLConnection下载

通过上面的两个方法去下载大文件是不合理的,因为这两个方法都是一次性返回整个下载到的文件,返回的data在内存中,如果下载一个几百兆的东西,内存肯定会爆的。其实NSURLConnection还提供了另外一种发送请求的方式

这里用到了代理,那肯定要遵守协议了.遵守 NSURLConnectionDataDelegate 协议.

进去看看有几个代理方法,其实我们能用到的也就三个。

 

通过执行下载操作,分别log上面三个方法,会发现didReceiveData这个方法会被频繁的调用,每次都会传回来一部分data,下面是官方api对这个方法的说明

is called with a single immutable NSData object to the delegate,representing the next portion of the data loaded from the connection. This is the only guaranteed for the delegate to receive the data from the resource load.

由此我们可以知道,这种下载方式是通过这个代理方法每次传回来一部分文件,最终我们把每次传回来的数据合并成一个我们需要的文件。

这时候我们通常想到的方法是定义一个全局的NSMutableData,接受到响应的时候初始化这个MutableData,在didReceiveData方法里面去拼接

[self.totalData appendData:data];

最后在完成下载的方法里面吧整个MutableData写入沙盒。

代码如下:

 

我这里下载的是javajdk。(度娘的地址)

注意:通常大文件下载是需要给用户展示下载进度的。

这个数值是 已经下载的数据大小/要下载的文件总大小

已经下载的数据我们可以记录,要下载的文件总大小在服务器返回的响应头里面可以拿到,在接受到响应的方法里执行

不得不说苹果太为开发者考虑了,我们不必这么麻烦的去获取文件总大小了,

response.expectedContentLength 这句代码就搞定了。

response.suggestedFilename 这句代表获取下载的文件名

这里写图片描述

题外话扯的有点多,言归正传,这样我们确实可以下载文件,最后拿到的文件也能正常运行

这里写图片描述

但是有个致命的问题,内存!用来接受文件的NSMutableData一直都在内存中,会随着文件的下载一直变大,

这里写图片描述

所有这种处理方式绝对是不合理的。

合理的方式在我们获取一部分data的时候就写入沙盒中,然后释放内存中的data。

这里要用到NSFilehandle这个类,这个类可以实现对文件的读取、写入、更新。

下面总结了一些常用的NSFileHandle的方法,在这个表中,fh是一个NSFileHandle对象,data是一个NSData对象,path是一个NSString 对象,offset是易额Unsigned long long变量。

这里写图片描述

具体关于NSFileHandle的用法各位自行搜索。

在接受到响应的时候就在沙盒中创建一个空的文件,然后每次接收到数据的时候就拼接到这个文件的最后面,通过 - (unsigned long long)seekToEndOfFile; 这个方法