本文共 4435 字,大约阅读时间需要 14 分钟。
#import <Foundation/Foundation.h> @class YGFileDownloader; @protocol YGFileDownloaderDelegate <NSObject> -(void)fileDownloader:(YGFileDownloader *)downloader downloadSize:(unsigned long long)downloadSize totalSize:(unsigned long long)totalSize; -(void)fileDownloaderDidFinishLoad; -(void)fileDownloaderFailWithError:(NSError *)error; @end @interface YGFileDownloader : NSObject @property (nonatomic,weak) id<YGFileDownloaderDelegate> delegate; +(instancetype)sharedInstance; -(void)start:(NSString *)urlStr; -(void)stop; @end#import "YGFileDownloader.h"
#import "NSString+util.h" @interface YGFileDownloader () <NSURLConnectionDataDelegate> @property (nonatomic,strong) NSURLConnection *connection; @property (nonatomic,copy) NSString *downloadDocPath;//这个路径标识我们下载的文件所存储的那个目录,他是写死的,每次下载东西都能放在目录下面 @property (nonatomic,strong) NSFileHandle *fileHandle; @property (nonatomic) unsigned long long downloadFileSize;//当前下载了多少(字节) @property (nonatomic) unsigned long long totalFileSize;//文件总大小 @end @implementation YGFileDownloader -(NSString *)downloadDocPath{ if (_downloadDocPath==nil) { //找到沙盒的Document目录 NSString *documentPath=[NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES) objectAtIndex:0]; //上面这句代码和 [NSHomeDirectory()stringByAppendingPathComponent:@"Documents"];一样 NSString *downloadPath=[documentPath stringByAppendingPathComponent:@"YGFileDownload"]; BOOL isSuccess=[[NSFileManager defaultManager] createDirectoryAtPath:downloadPath withIntermediateDirectories:YES attributes:nil error:nil]; if (isSuccess) { NSLog(@"创建文件夹成功"); } _downloadDocPath=downloadPath; } return _downloadDocPath; } +(instancetype)sharedInstance{//创建单例对象 static YGFileDownloader *downloader=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken,^{//大括号里的代码只会执行一次 downloader=[[YGFileDownloader alloc] init]; }); return downloader; } -(void)start:(NSString *)urlStr{ NSString *fullPath=[self prepareStart:urlStr]; //获取fullPath标识的文件的大小 _downloadFileSize=[self readDownloadFileSize:fullPath]; NSMutableURLRequest *request=[[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:urlStr]]; [request addValue:[NSString stringWithFormat:@"bytes=%llu-",_downloadFileSize] forHTTPHeaderField:@"Range"];//告诉服务器请求_downloadFileSize以后的字节 self.connection=[[NSURLConnection alloc] initWithRequest:request delegate:self]; } -(NSString *)prepareStart:(NSString *)urlStr{//确保urlStr所对应的沙盒的位置上有文件 NSString *fileName=urlStr.md5;//把url所对应的MD5值作为文件名 //fullPath代表这个文件具体的位置(路径) NSString *fullPath=[self.downloadDocPath stringByAppendingString:fileName]; //如果指定的这个路径下面不存在这个文件,我们就把他创建出来 BOOL fileExists=[[NSFileManager defaultManager] fileExistsAtPath:fullPath]; if (!fileExists) { [[NSFileManager defaultManager] createFileAtPath:fullPath contents:nil attributes:nil]; } //打开这个文件准备往里面写数据 self.fileHandle=[NSFileHandle fileHandleForWritingAtPath:fullPath]; return fullPath; //这个函数的功能是在准备下载文件之前做一些准备工作:1.确保文件存在,2.打开文件准备往里面写数据,3.获取这个文件的确切路径,因为我们在往这个路径所标识的这个文件中写数据(我们下载的数据) } -(unsigned long long)readDownloadFileSize:(NSString *)filePath{//读取filePath文件的文件大小 NSDictionary *fileInfo=[[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil]; return [fileInfo fileSize]; } -(void)stop{ [_connection cancel],_connection=nil; [_fileHandle closeFile],_fileHandle=nil; } #pragma mark - <NSURLConnectionDataDelegate> -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{ _totalFileSize=_downloadFileSize+response.expectedContentLength; } -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{ if ([self.delegate conformsToProtocol:@protocol(YGFileDownloaderDelegate)]&&[self.delegate respondsToSelector:@selector(fileDownloaderFailWithError:)]) { [self.delegate fileDownloaderFailWithError:error]; } } -(void)connectionDidFinishLoading:(NSURLConnection *)connection{ if ([self.delegate respondsToSelector:@selector(fileDownloaderDidFinishLoad)]) { [self.delegate fileDownloaderDidFinishLoad]; } } -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{ [_fileHandle seekToEndOfFile];//设置在末尾追加数据 [_fileHandle writeData:data];//写入数据 _downloadFileSize += data.length; if ([self.delegate conformsToProtocol:@protocol(YGFileDownloaderDelegate)] && [self.delegate respondsToSelector:@selector(fileDownloader:downloadSize:totalSize:)]) { [self.delegate fileDownloader:self downloadSize:_downloadFileSize totalSize:_totalFileSize]; } } @end转载地址:http://jjsni.baihongyu.com/