使用NSURLConnection实现大文件断点下载
来源:互联网 发布:yum安装的mysql在哪里 编辑:程序博客网 时间:2024/05/18 01:18
由于是实现大文件的断点下载,不是下载一般图片什么的.在设计这个类的时候本身就不会考虑把下载的文件缓存到内存中,而是直接写到文件系统.
要实现断点下载,需要满足1个条件,那就是,必须要服务器支持断点下载.
实现的思路是这样子的:
1. 第一次会获取到被下载文件的总大小(服务器提供这个值)
下载文件总大小 = 期望从服务器获取文件的大小 + 本地已经下载的文件的大小
2. 设置请求的缓存策略为不会读取本地中已经缓存的数据(NSURLRequestReloadIgnoringLocalCacheData)
3. 在去服务器请求数据之前先获取到本地已经下载好的部分文件的长度,以这个参数设置进Range中到服务器去请求剩下的数据
4. 当从网络获取到一定的数据的时候,我们直接将数据写进文件系统中
YXDownloadNetwork.h
//// YXDownloadNetwork.h// Download//// http://home.cnblogs.com/u/YouXianMing///// Copyright (c) 2014年 Y.X. All rights reserved.//#import <Foundation/Foundation.h>// block的相关定义typedef void (^downloadProgress_t)(long long currentBytes, long long totalBytes);typedef void (^completion_t)(NSDictionary *headers, NSData *body);@interface YXDownloadNetwork : NSObject// 将block定义成属性@property (nonatomic, copy) downloadProgress_t downloadProgress;@property (nonatomic, copy) completion_t completion;// 初始化方法- (instancetype)initWithUrlString:(NSString *)urlString cacheCapacity:(unsigned long long)capacity;- (void)start;@end
YXDownloadNetwork.m
//// YXDownloadNetwork.m// Download//// http://home.cnblogs.com/u/YouXianMing///// Copyright (c) 2014年 Y.X. All rights reserved.//#import "YXDownloadNetwork.h"@interface YXDownloadNetwork ()<NSURLConnectionDelegate, NSURLConnectionDataDelegate>@property (nonatomic, assign) unsigned long long totalLength; // 文件总大小@property (nonatomic, assign) unsigned long long startDataLength; // 本地存在文件的大小@property (nonatomic, assign) unsigned long long expectedLength; // 从服务器期望文件的大小@property (nonatomic, assign) unsigned long long cacheCapacity; // 缓存文件容量,以k为单位@property (nonatomic, strong) NSURLConnection *dataConncetion; // 网络连接@property (nonatomic, strong) NSDictionary *responseHeaders; // 网络连接头部信息@property (nonatomic, strong) NSFileHandle *file; // 文件操作句柄@property (nonatomic, strong) NSMutableData *cacheData; // 用于缓存的data数据@end@implementation YXDownloadNetwork- (instancetype)initWithUrlString:(NSString *)urlString cacheCapacity:(unsigned long long)capacity{ self = [super init]; if (self) { // 获取缓存容量 if (capacity <= 0) { _cacheCapacity = 100 * 1024; } else { _cacheCapacity = capacity * 1024; } // 获取用于缓存的数据 _cacheData = [NSMutableData new]; // 获取文件名以及文件路径 NSString *fileName = [urlString lastPathComponent]; NSString *filePath = \ fileFromPath([NSString stringWithFormat:@"/Documents/%@", fileName]); // 记录文件起始位置 if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) { // 从文件中读取出已经下载好的文件的长度 _startDataLength = [[NSData dataWithContentsOfFile:filePath] length]; } else { // 不存在则创建文件 _startDataLength = 0; [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil]; } // 打开写文件流 _file = [NSFileHandle fileHandleForWritingAtPath:filePath]; // 创建一个网络请求 NSMutableURLRequest* request = \ [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]]; // 禁止读取本地缓存 [request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData]; // 设置断点续传(需要服务器支持) [request setValue:[NSString stringWithFormat:@"bytes=%llu-", _startDataLength] forHTTPHeaderField:@"Range"]; // 开始创建连接 self.dataConncetion = \ [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO]; } return self;}- (void)start{ [self.dataConncetion start];}- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{ if([response isKindOfClass:[NSHTTPURLResponse class]]) { NSHTTPURLResponse *r = (NSHTTPURLResponse *)response; // 如果能获取到期望的数据长度就执行括号中的方法 if ([r expectedContentLength] != NSURLResponseUnknownLength) { // 获取剩余要下载的 _expectedLength = [r expectedContentLength]; // 计算出总共需要下载的 _totalLength = _expectedLength + _startDataLength; // 获取头文件 _responseHeaders = [r allHeaderFields]; } else { NSLog(@"不支持断点下载"); } }}- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)theData{ // 追加缓存数据 [_cacheData appendData:theData]; // 如果该缓存数据的大小超过了指定的缓存大小 if ([_cacheData length] >= _cacheCapacity) { // 移动到文件结尾 [_file seekToEndOfFile]; // 在文件末尾处追加数据 [_file writeData:_cacheData]; // 清空缓存数据 [_cacheData setLength:0]; } // 当前已经下载的所有数据的总量 _startDataLength += [theData length]; // 如果指定了block if (_downloadProgress) { _downloadProgress(_startDataLength, _totalLength); }}- (void)connectionDidFinishLoading:(NSURLConnection *)connection{ // 移动到文件结尾 [_file seekToEndOfFile]; // 在文件末尾处追加最后的一点缓存数据 [_file writeData:_cacheData]; // 清空缓存 [_cacheData setLength:0]; NSLog(@"下载完成哦");}NS_INLINE NSString * fileFromPath(NSString *filePath){ return [NSHomeDirectory() stringByAppendingString:filePath];}@end
测试代码如下:
0 0
- 使用NSURLConnection实现大文件断点下载
- 使用NSURLConnection实现大文件断点下载
- 使用NSURLConnection实现大文件断点下载
- 使用NSURLConnection实现断点下载
- NSURLSession NSURLConnection下载大文件 断点下载
- NSURLConnection实现大文件下载
- iOS开发网络篇 一一 NSURLConnection-大文件断点下载
- NSURLConnection下载大文件
- NSURLConnection下载大小文件,断点下载
- iOS开发 使用NSURLConnection实现下载文件
- IOS - NSURLConnection大文件下载
- NSURLConnection下载一个大文件
- iOS网络--『文件下载、断点下载』的实现(一):NSURLConnection
- IOS - NSURLConnection断点下载
- NSURLConnection和NSURLSession大文件下载
- 网络---大文件的下载(NSURLConnection)
- (有码)NSURLConnection大文件下载
- 大文件离线断点下载
- 算法学习 - 最长公共子序列(LCS)C++实现
- FZU-2150 Fire Game
- UVA - 1459 Flowers Placement(二分图+dfs)
- 优化Markdown在Notepad++中的使用体验
- Hadoop(最新版ChainMapper链接MapReduce作业带原理分析)
- 使用NSURLConnection实现大文件断点下载
- Gulp帮你自动搞定coffee和scss的compile
- HDU 4415 Assassin's Creed(贪心)
- 那些年
- STL
- 如何快速地在上千台服务器上部署一项服务
- 最后的约定
- UVALive - 3353 Optimal Bus Route Design(二分图最佳匹配)
- See LCS again 最长递增子序列到最长公共子序列的转化