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

 

posted @ 2015-11-25 17:57  晨光微  阅读(173)  评论(0编辑  收藏  举报