iOS网络-通过NSURLConnection文件下载,断点下载,输出流下载
2016-01-17 11:44
525 查看
小文件下载
NSURLConnection-delegate实现,可以监听到下载的进度,但是还是无法解决内存飙升的问题,所以仅限小文件下载
大文件下载
NSURLConnection-delegate实现, 实现思路:
大文件断点下载
实现思路: 设置请求头NSFileHandle
1.设置请求头,在开始下载的时候设置
2.注意点(下载进度并判断是否需要重新创建文件)
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response接收到服务器的响应的方法中代码改动:
//文件的总大小 == 本次要下载的文件大小 + 已经下载的文件的大小
self.totalLength = response.expectedContentLength + self.currentLength;
// 判断当前是否已经下载过,如果当前文件已经存在,那么直接返回,不然新下载的大小会覆盖原来文件,导致前面文件丢失
if (self.currentLength >0) {
return;
}[/code]
大文件输出流下载
使用输出流也可以实现和NSFileHandle相同的功能
NSURLConnection-delegate实现,可以监听到下载的进度,但是还是无法解决内存飙升的问题,所以仅限小文件下载
@interface ViewController ()<NSURLConnectionDataDelegate> @property (weak, nonatomic) IBOutlet UIProgressView *progressView; /** 接收数据的data */ @property (nonatomic, strong) NSMutableData *fileData; /*文件名称 */ @property (nonatomic, strong) NSString *fileName; @property (nonatomic, assign) NSInteger totalSize; @end @implementation ViewController -(NSMutableData *)fileData { if (_fileData == nil) { _fileData = [NSMutableData data]; } return _fileData; } -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { //1.确定URL NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"]; //2.创建请求对象 NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url]; //3.设置代理,发送请求 [NSURLConnection connectionWithRequest:request delegate:self]; } #pragma mark - NSURLConnectionDataDelegate -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { //suggestedFilename:服务器端推荐的名称,其实就是url的最后一个节点 self.fileName = response.suggestedFilename; //expectedContentLength:获得文件总大小 self.totalSize = response.expectedContentLength; } -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { //拼接数据 [self.fileData appendData:data]; //计算文件的下载进度== 已经下载的大小/文件的总大小 NSLog(@"%f",1.0 * self.fileData.length /self.totalSize); //进度UI self.progressView.progress = 1.0 * self.fileData.length /self.totalSize; } -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { } -(void)connectionDidFinishLoading:(NSURLConnection *)connection { //写数据到磁盘 NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; //拼接全路径 NSString *fullPath = [caches stringByAppendingPathComponent:self.fileName]; //写沙盒 [self.fileData writeToFile:fullPath atomically:YES]; } @end
大文件下载
NSURLConnection-delegate实现, 实现思路:
边接收数据边写文件以解决内存越来越大的问题
@interface ViewController ()<NSURLConnectionDataDelegate> @property (weak, nonatomic) IBOutlet UIProgressView *progressView; /*文件名称 */ @property (nonatomic, strong) NSString *fileName; /*文件的总大小*/ @property (nonatomic, assign) NSInteger totalSize; /*已经下载的文件大小*/ @property (nonatomic, assign) NSInteger currentSize; /** 文件句柄 */ @property (nonatomic, strong) NSFileHandle *handle; @end @implementation ViewController -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { //1.确定URL NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"]; //2.创建请求对象 NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url]; //3.设置代理,发送请求 [NSURLConnection connectionWithRequest:request delegate:self]; } #pragma mark - NSURLConnectionDataDelegate //接收到服务器的响应 -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { //1.获得caches目录 NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; //2.拼接全路径 NSString *fullPath = [caches stringByAppendingPathComponent:response.suggestedFilename]; //3.获得本次请求的文件数据大小(期望大小) self.totalSize = response.expectedContentLength; //4.新建一个空的文件 /* 第一个参数:文件的目录 第二个参数:文件的内容 第三个参数:文件的属性 */ [[NSFileManager defaultManager]createFileAtPath:fullPath contents:nil attributes:nil]; //5.创建文件句柄 NSFileHandle *handle = [NSFileHandle fileHandleForWritingAtPath:fullPath]; self.handle = handle; } //接收到服务器返回的数据 -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { //1.移动文件句柄到文件的末尾 [self.handle seekToEndOfFile]; //2.写数据到磁盘 [self.handle writeData:data]; //3.计算文件的下载进度== 已经下载的大小/文件的总大小 self.currentSize +=data.length; NSLog(@"%f",1.0 * self.currentSize /self.totalSize); //4.进度UI self.progressView.progress = 1.0 * self.currentSize /self.totalSize; } //请求完成 -(void)connectionDidFinishLoading:(NSURLConnection *)connection { //释放文件句柄 [self.handle closeFile]; self.handle = nil; } @end
大文件断点下载
实现思路: 设置请求头NSFileHandle
在下载文件的时候不再是整块的从头开始下载,而是看当前文件已经下载到哪个地方,然后从该地方接着往后面下载。可以通过在请求对象中设置请求头实现。
1.设置请求头,在开始下载的时候设置
//2.创建请求对象 可变的 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; //2.1 设置下载文件的某一部分 // 只要设置HTTP请求头的Range属性, 就可以实现从指定位置开始下载 /* 表示头500个字节:Range: bytes=0-499 表示第二个500字节:Range: bytes=500-999 表示最后500个字节:Range: bytes=-500 表示500字节以后的范围:Range: bytes=500- */ NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentLength]; [request setValue:range forHTTPHeaderField:@"Range"];
2.注意点(下载进度并判断是否需要重新创建文件)
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response接收到服务器的响应的方法中代码改动:
//注意点:[code]response.expectedContentLength获得是本次请求要下载的文件的大小(并非是完整的文件的大小)
//文件的总大小 == 本次要下载的文件大小 + 已经下载的文件的大小
self.totalLength = response.expectedContentLength + self.currentLength;
// 判断当前是否已经下载过,如果当前文件已经存在,那么直接返回,不然新下载的大小会覆盖原来文件,导致前面文件丢失
if (self.currentLength >0) {
return;
}[/code]
大文件输出流下载
使用输出流也可以实现和NSFileHandle相同的功能
//1.创建一个数据输出流 /* 第一个参数:二进制的流数据要写入到哪里 第二个参数:采用什么样的方式写入流数据,如果YES则表示追加,如果是NO则表示覆盖 */ NSOutputStream *stream = [NSOutputStream outputStreamToFileAtPath:fullPath append:YES]; //只要调用了该方法就会往文件中写数据 //如果文件不存在,那么会自动的创建一个 [stream open]; self.stream = stream; //2.当接收到数据的时候写数据 //使用输出流写数据 /* 第一个参数:要写入的二进制数据 第二个参数:要写入的数据的大小 */ [self.stream write:data.bytes maxLength:data.length]; //3.当文件下载完毕的时候关闭输出流 //关闭输出流 [self.stream close]; self.stream = nil;
相关文章推荐
- (UNP)问题小结
- 初识AJAX
- 关于TCP/IP
- Linux网络管理
- httpd2.4在CentOS 6 上编译安装
- http://www.linuxidc.com/Linux/2015-02/114265.htm
- php的curl获取https加密协议请求返回json数据进行信息获取
- linux中网络配置文件/eth/sysconfig/network-scripts/ifcfg-ethX以及ifup|ifdown小结
- linux网络配置命令ip(ifconfig+route)小结
- iOS网络编程-http
- Ansible用于网络设备管理 part 3 使用NAPALM成品库
- 在与SQLServer建立连接时出现与网络相关的或特定于实例的错误40
- 《tcp/ip协议族》阅读思考一
- nefu482方格取数【最大点权独立集】网络流24题
- 腾讯QQ、新浪微博等知名社交网络图标素材
- 网站网络带宽 和 流量的区别
- 网络爬虫入门(一)
- linux下强大的网络管理工具ethtool学习小结
- UWP——HttpClient模拟浏览器的GET、POST请求之Win10 Mobile测试
- JAVA网络编程