iOS开发 -------- AFNetworking实现简单的断点下载
一 实现如下效果
二 实现代码
1 // 2 // ViewController.m 3 // AFNetworking实现断点下载 4 // 5 // Created by lovestarfish on 15/11/15. 6 // Copyright © 2015年 S&G. All rights reserved. 7 // 8 #define kURL @"http://v.hoto.cn/cc/45/869836.mp4?v=4" 9 #import "ViewController.h" 10 #import "AFNetworking.h" 11 12 @interface ViewController () 13 14 @property (weak, nonatomic) IBOutlet UILabel *progressLabel; 15 @property (weak, nonatomic) IBOutlet UIProgressView *progressView; 16 @property (nonatomic,strong) AFHTTPRequestOperation *operation; 17 18 - (IBAction)start:(UIButton *)sender; 19 20 @end 21 22 @implementation ViewController 23 24 - (void)viewDidLoad { 25 [super viewDidLoad]; 26 27 // 获取保存下载进度的缓存文件 28 NSString *txtTempPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"mvTemp/mv.txt"]; 29 NSLog(@"%@",txtTempPath); 30 NSFileManager *fileManager = [NSFileManager defaultManager]; 31 32 33 // 判断文件夹里面有没有之前的缓存文件 34 if ([fileManager fileExistsAtPath:txtTempPath]) { 35 // 有的话继续之前的下载进度下载 36 self.progressView.progress = [[NSString stringWithContentsOfFile:txtTempPath encoding:NSUTF8StringEncoding error:nil] floatValue]; 37 } else { 38 // 没有的话进度从0开始 39 self.progressView.progress = 0; 40 } 41 42 // 设置显示进度的label内容 43 self.progressLabel.text = [NSString stringWithFormat:@"%.2f%%",self.progressView.progress * 100]; 44 45 NSLog(@"%@",NSHomeDirectory()); 46 } 47 48 /** 49 * 开始下载(下载的时候判断是否已经下载过该文件) 50 */ 51 - (IBAction)start:(UIButton *)sender { 52 // 创建文件管理对象 53 NSFileManager *fileManager = [NSFileManager defaultManager]; 54 // 视频文件 55 NSString *mp4Path = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches/mv/mv.mp4"]; 56 // 视频文件夹 57 NSString *mvPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches/mv"]; 58 //缓存文件夹 59 NSString *mvTempPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"mvTemp"]; 60 61 // 如果存在mp4Path路径则说明已经下载该文件,此时提示用户是否需要重新下载 62 if ([fileManager fileExistsAtPath:mp4Path]) {// 存在该文件 63 UIAlertController *alertC = [UIAlertController alertControllerWithTitle:@"提示" message:@"文件已经存在,是否重新下载" preferredStyle:UIAlertControllerStyleAlert]; 64 // 确定行为 65 UIAlertAction *doneAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { 66 NSLog(@"点击了确定"); 67 // 重新下载,需要移除之前的视频文件夹和缓存文件夹 68 [fileManager removeItemAtPath:mvPath error:nil];//视频文件夹 69 [fileManager removeItemAtPath:mvTempPath error:nil];//缓存文件夹 70 [self download:sender]; 71 }]; 72 73 // 取消行为 74 UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { 75 // 点击取消,直接return 76 NSLog(@"点击了取消"); 77 return ; 78 }]; 79 80 // 添加行为到控制器alertC 81 [alertC addAction:doneAction]; 82 [alertC addAction:cancelAction]; 83 84 // 模态弹出提示框 85 [self presentViewController:alertC animated:YES completion:nil]; 86 } else { // 不存在,直接下载 87 [self download:sender]; 88 } 89 } 90 91 /** 92 * 下载操作 93 */ 94 - (void)download:(UIButton *)sender { 95 NSFileManager *fileManager = [NSFileManager defaultManager]; 96 if ([sender.currentTitle isEqualToString:@"开始下载"]) { 97 // 如果已经开始下载,将按钮标题置为"暂停下载" 98 [sender setTitle:@"暂停下载" forState:UIControlStateNormal]; 99 100 // 下载的url 101 NSURL *url = [NSURL URLWithString:kURL]; 102 // 获取cache文件夹 103 NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]; 104 105 // 在cache文件夹创建mv文件夹,用来存放下载成功地资料 106 NSString *folderPath = [cachePath stringByAppendingPathComponent:@"mv"]; 107 // 在缓存文件夹里创建mvTemp文件夹用来临时存放下载信息 108 NSString *tempPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"mvTemp"]; 109 // 判断缓存文件夹和视频存放文件夹是否存在,如果不存在,就创建一个文件夹 110 if (![fileManager fileExistsAtPath:folderPath]) {// 如果不存在视频文件夹 111 [fileManager createDirectoryAtPath:folderPath withIntermediateDirectories:YES attributes:nil error:nil]; 112 } 113 if (![fileManager fileExistsAtPath:tempPath]) { // 如果不存在缓存文件夹 114 [fileManager createDirectoryAtPath:tempPath withIntermediateDirectories:YES attributes:nil error:nil]; 115 } 116 117 // 缓存路径(缓存当前下载的容量值) 118 NSString *tempFilePath = [tempPath stringByAppendingPathComponent:@"mv.temp"]; 119 120 // 保存重启程序下载的进度(保存当前下载的进度值) 121 NSString *txtFilePath = [tempPath stringByAppendingPathComponent:@"mv.txt"]; 122 123 // 文件保存路径 124 NSString *mvFilePath = [folderPath stringByAppendingPathComponent:@"mv.mp4"]; 125 126 // 初始化下载字节数为0 127 unsigned long long downloadedBytes = 0; 128 // 创建请求 129 NSURLRequest *request = [NSURLRequest requestWithURL:url]; 130 if ([fileManager fileExistsAtPath:tempFilePath]) {//如果存在,说明有缓存文件 131 // 计算缓存文件的大小 132 downloadedBytes = [self fileSizeAtPath:tempFilePath]; 133 NSLog(@"%llu",downloadedBytes); 134 // 创建可变请求 135 NSMutableURLRequest *mutableRequest = [request mutableCopy]; 136 NSString *requestRange = [NSString stringWithFormat:@"bytes=%llu-",downloadedBytes]; 137 138 [mutableRequest setValue:requestRange forHTTPHeaderField:@"Range"]; 139 request = mutableRequest; 140 NSLog(@"==============断点下载"); 141 } 142 143 if (![fileManager fileExistsAtPath:mvFilePath]) { 144 [[NSURLCache sharedURLCache] removeCachedResponseForRequest:request]; 145 self.operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; 146 [self.operation setOutputStream:[NSOutputStream outputStreamToFileAtPath:tempFilePath append:YES]]; 147 148 // 设置下载进度的block 149 __block ViewController *vc = self; 150 [self.operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { 151 // 更新进度 152 vc.progressView.progress = ((float)totalBytesRead + downloadedBytes)/ (totalBytesExpectedToRead + downloadedBytes); 153 vc.progressLabel.text = [NSString stringWithFormat:@"%.2f%%",self.progressView.progress * 100]; 154 // 将进度写入缓存文件 155 NSString *progress = [NSString stringWithFormat:@"%.3f",((float)totalBytesRead + downloadedBytes) / ( totalBytesExpectedToRead + downloadedBytes)]; 156 [progress writeToFile:txtFilePath atomically:YES encoding:NSUTF8StringEncoding error:nil]; 157 }]; 158 159 // 下载完成时调用 160 [self.operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation * _Nonnull operation, id _Nonnull responseObject) { 161 //把下载完成的文件转移到保存的路径 162 [fileManager moveItemAtPath:tempFilePath toPath:mvFilePath error:nil]; 163 //删除保存进度的txt文档 164 [fileManager removeItemAtPath:txtFilePath error:nil]; 165 [sender setTitle:@"下载完成" forState:UIControlStateNormal]; 166 } failure:^(AFHTTPRequestOperation * _Nonnull operation, NSError * _Nonnull error) { 167 168 }]; 169 170 // 开始操作 171 [self.operation start]; 172 } 173 } else { 174 [sender setTitle:@"开始下载" forState:UIControlStateNormal]; 175 [self.operation cancel]; 176 self.operation = nil; 177 } 178 179 } 180 181 /** 182 * 计算缓存文件的大小 183 * 184 * @param fileAbsolutePath 文件的绝对路径 185 * 186 * @return 文件的大小 187 */ 188 - (unsigned long long)fileSizeAtPath:(NSString *)fileAbsolutePath { 189 signed long long fileSize = 0; 190 NSFileManager *fileManager = [NSFileManager new]; 191 if ([fileManager fileExistsAtPath:fileAbsolutePath]) { 192 NSError *error = nil; 193 NSDictionary *fileDict = [fileManager attributesOfItemAtPath:fileAbsolutePath error:&error]; 194 if (!error && fileDict) { 195 fileSize = [fileDict fileSize]; 196 } 197 } 198 return fileSize; 199 } 200 201 @end