iOS开发 -------- AFNetworking实现简单的断点下载
一 实现如下效果
二 实现代码
//
// ViewController.m
// AFNetworking实现断点下载
//
// Created by lovestarfish on 15/11/15.
// Copyright © 2015年 S&G. All rights reserved.
//
#define kURL @"http://v.hoto.cn/cc/45/869836.mp4?v=4"
#import "ViewController.h"
#import "AFNetworking.h" @interface ViewController () @property (weak, nonatomic) IBOutlet UILabel *progressLabel;
@property (weak, nonatomic) IBOutlet UIProgressView *progressView;
@property (nonatomic,strong) AFHTTPRequestOperation *operation; - (IBAction)start:(UIButton *)sender; @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad]; // 获取保存下载进度的缓存文件
NSString *txtTempPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"mvTemp/mv.txt"];
NSLog(@"%@",txtTempPath);
NSFileManager *fileManager = [NSFileManager defaultManager]; // 判断文件夹里面有没有之前的缓存文件
if ([fileManager fileExistsAtPath:txtTempPath]) {
// 有的话继续之前的下载进度下载
self.progressView.progress = [[NSString stringWithContentsOfFile:txtTempPath encoding:NSUTF8StringEncoding error:nil] floatValue];
} else {
// 没有的话进度从0开始
self.progressView.progress = ;
} // 设置显示进度的label内容
self.progressLabel.text = [NSString stringWithFormat:@"%.2f%%",self.progressView.progress * ]; NSLog(@"%@",NSHomeDirectory());
} /**
* 开始下载(下载的时候判断是否已经下载过该文件)
*/
- (IBAction)start:(UIButton *)sender {
// 创建文件管理对象
NSFileManager *fileManager = [NSFileManager defaultManager];
// 视频文件
NSString *mp4Path = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches/mv/mv.mp4"];
// 视频文件夹
NSString *mvPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches/mv"];
//缓存文件夹
NSString *mvTempPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"mvTemp"]; // 如果存在mp4Path路径则说明已经下载该文件,此时提示用户是否需要重新下载
if ([fileManager fileExistsAtPath:mp4Path]) {// 存在该文件
UIAlertController *alertC = [UIAlertController alertControllerWithTitle:@"提示" message:@"文件已经存在,是否重新下载" preferredStyle:UIAlertControllerStyleAlert];
// 确定行为
UIAlertAction *doneAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
NSLog(@"点击了确定");
// 重新下载,需要移除之前的视频文件夹和缓存文件夹
[fileManager removeItemAtPath:mvPath error:nil];//视频文件夹
[fileManager removeItemAtPath:mvTempPath error:nil];//缓存文件夹
[self download:sender];
}]; // 取消行为
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
// 点击取消,直接return
NSLog(@"点击了取消");
return ;
}]; // 添加行为到控制器alertC
[alertC addAction:doneAction];
[alertC addAction:cancelAction]; // 模态弹出提示框
[self presentViewController:alertC animated:YES completion:nil];
} else { // 不存在,直接下载
[self download:sender];
}
} /**
* 下载操作
*/
- (void)download:(UIButton *)sender {
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([sender.currentTitle isEqualToString:@"开始下载"]) {
// 如果已经开始下载,将按钮标题置为"暂停下载"
[sender setTitle:@"暂停下载" forState:UIControlStateNormal]; // 下载的url
NSURL *url = [NSURL URLWithString:kURL];
// 获取cache文件夹
NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]; // 在cache文件夹创建mv文件夹,用来存放下载成功地资料
NSString *folderPath = [cachePath stringByAppendingPathComponent:@"mv"];
// 在缓存文件夹里创建mvTemp文件夹用来临时存放下载信息
NSString *tempPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"mvTemp"];
// 判断缓存文件夹和视频存放文件夹是否存在,如果不存在,就创建一个文件夹
if (![fileManager fileExistsAtPath:folderPath]) {// 如果不存在视频文件夹
[fileManager createDirectoryAtPath:folderPath withIntermediateDirectories:YES attributes:nil error:nil];
}
if (![fileManager fileExistsAtPath:tempPath]) { // 如果不存在缓存文件夹
[fileManager createDirectoryAtPath:tempPath withIntermediateDirectories:YES attributes:nil error:nil];
} // 缓存路径(缓存当前下载的容量值)
NSString *tempFilePath = [tempPath stringByAppendingPathComponent:@"mv.temp"]; // 保存重启程序下载的进度(保存当前下载的进度值)
NSString *txtFilePath = [tempPath stringByAppendingPathComponent:@"mv.txt"]; // 文件保存路径
NSString *mvFilePath = [folderPath stringByAppendingPathComponent:@"mv.mp4"]; // 初始化下载字节数为0
unsigned long long downloadedBytes = ;
// 创建请求
NSURLRequest *request = [NSURLRequest requestWithURL:url];
if ([fileManager fileExistsAtPath:tempFilePath]) {//如果存在,说明有缓存文件
// 计算缓存文件的大小
downloadedBytes = [self fileSizeAtPath:tempFilePath];
NSLog(@"%llu",downloadedBytes);
// 创建可变请求
NSMutableURLRequest *mutableRequest = [request mutableCopy];
NSString *requestRange = [NSString stringWithFormat:@"bytes=%llu-",downloadedBytes]; [mutableRequest setValue:requestRange forHTTPHeaderField:@"Range"];
request = mutableRequest;
NSLog(@"==============断点下载");
} if (![fileManager fileExistsAtPath:mvFilePath]) {
[[NSURLCache sharedURLCache] removeCachedResponseForRequest:request];
self.operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[self.operation setOutputStream:[NSOutputStream outputStreamToFileAtPath:tempFilePath append:YES]]; // 设置下载进度的block
__block ViewController *vc = self;
[self.operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
// 更新进度
vc.progressView.progress = ((float)totalBytesRead + downloadedBytes)/ (totalBytesExpectedToRead + downloadedBytes);
vc.progressLabel.text = [NSString stringWithFormat:@"%.2f%%",self.progressView.progress * ];
// 将进度写入缓存文件
NSString *progress = [NSString stringWithFormat:@"%.3f",((float)totalBytesRead + downloadedBytes) / ( totalBytesExpectedToRead + downloadedBytes)];
[progress writeToFile:txtFilePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
}]; // 下载完成时调用
[self.operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation * _Nonnull operation, id _Nonnull responseObject) {
//把下载完成的文件转移到保存的路径
[fileManager moveItemAtPath:tempFilePath toPath:mvFilePath error:nil];
//删除保存进度的txt文档
[fileManager removeItemAtPath:txtFilePath error:nil];
[sender setTitle:@"下载完成" forState:UIControlStateNormal];
} failure:^(AFHTTPRequestOperation * _Nonnull operation, NSError * _Nonnull error) { }]; // 开始操作
[self.operation start];
}
} else {
[sender setTitle:@"开始下载" forState:UIControlStateNormal];
[self.operation cancel];
self.operation = nil;
} } /**
* 计算缓存文件的大小
*
* @param fileAbsolutePath 文件的绝对路径
*
* @return 文件的大小
*/
- (unsigned long long)fileSizeAtPath:(NSString *)fileAbsolutePath {
signed long long fileSize = ;
NSFileManager *fileManager = [NSFileManager new];
if ([fileManager fileExistsAtPath:fileAbsolutePath]) {
NSError *error = nil;
NSDictionary *fileDict = [fileManager attributesOfItemAtPath:fileAbsolutePath error:&error];
if (!error && fileDict) {
fileSize = [fileDict fileSize];
}
}
return fileSize;
} @end
iOS开发 -------- AFNetworking实现简单的断点下载的更多相关文章
- iOS开发网络篇—简单介绍ASI框架的使用
iOS开发网络篇—简单介绍ASI框架的使用 说明:本文主要介绍网络编程中常用框架ASI的简单使用. 一.ASI简单介绍 ASI:全称是ASIHTTPRequest,外号“HTTP终结者”,功能十分强大 ...
- iOS开发之常用第三方框架(下载地址,使用方法,总结)
iOS开发之常用第三方框架(下载地址,使用方法,总结) 说句实话,自学了这么久iOS,如果说我不知道的但是又基本上都摸遍了iOS相关知识,但是每次做项目的时候,遇到难一点的地方或者没试过的东西就闷了. ...
- iOS开发UI篇—简单的浏览器查看程序
iOS开发UI篇—简单的浏览器查看程序 一.程序实现要求 1.要求 2. 界面分析 (1) 需要读取或修改属性的控件需要设置属性 序号标签 图片 图片描述 左边按钮 右边按钮 (2) 需要监听响应事件 ...
- iOS开发UI篇—简单介绍静态单元格的使用
iOS开发UI篇—简单介绍静态单元格的使用 一.实现效果与说明 说明:观察上面的展示效果,可以发现整个界面是由一个tableview来展示的,上面的数据都是固定的,且几乎不会改变. 要完成上面的效果, ...
- iOS开发Swift篇—简单介绍
iOS开发Swift篇—简单介绍 一.简介 Swift是苹果于2014年WWDC(苹果开发者大会)发布的全新编程语言 Swift在天朝译为“雨燕”,是它的LOGO 是一只燕子,跟Objective-C ...
- 李洪强iOS开发之- 实现简单的弹窗
李洪强iOS开发之- 实现简单的弹窗 实现的效果: 112222222222223333333333333333
- IOS开发苹果官方Sample Code及下载地址
IOS开发苹果官方Sample Code及下载地址 在线浏览地址:https://developer.apple.com/library/ios/navigation/#section=Resourc ...
- iOS开发笔记,简单实现视频音频的边下边播
总是在网上看别人的博文,受益匪浅,从没自己写过,今天分享一点小经验,第一次写技术博客,希望对同行的ios猿们有所帮助. 先介绍一下自己的情况:一年ios开发,http协议不太懂,大约知道断点下载h ...
- ios网络 -- HTTP请求 and 文件下载/断点下载
一:请求 http://www.jianshu.com/p/8a90aa6bad6b 二:下载 iOS网络--『文件下载.断点下载』的实现(一):NSURLConnection http://www. ...
随机推荐
- Vue2学习笔记:计算属性(computed)
参考:https://www.cnblogs.com/zycbloger/p/6428907.html
- vue+axios如何操作数据交互
参考: http://www.php.cn/js-tutorial-403543.html
- php算法题
一群猴子排成一圈,按1,2,…,n依次编号.然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数,再数到第m只,在把它踢出去…,如此不停的进行下去,直到最后只剩下一只猴子为止,那只猴子就叫做大 ...
- FatMouse' Trade(杭电ACM---1009)
FatMouse' Trade Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)T ...
- en-zh(社会问题)social problems-2
让屏幕代替父母陪孩子?世卫组织:这样是不对的! No sedentary screen time for babies, WHO says Babies and toddlers should not ...
- 移动前端开发和 Web 前端开发的区别
http://www.itcast.cn/news/20180125/16033584753.shtml 1,普通PC端开发与移动端开发区别. 先说背景,我大言不惭的说一下,我pc端的前端开发干了有快 ...
- C++11 使用异步编程std::async和std::future
先说明一点:std::asyanc是std::future的高级封装, 一般我们不会直接使用std::futrue,而是使用对std::future的高级封装std::async. 下面分别说一下. ...
- Intro to Mongoid
Mongoid: object-document-mapper(ODM) Mongoid Configuration: rails g mongoid:config Document: Documen ...
- MongoDB "$" 字符 下标位置
我们可以修改列表里面元素的名字 例如: 修改age=34的数据,hobby里面的"足球"改为"网球" }) { "_id" : Object ...
- final、finally、finalize区别
final final关键字可以用来修饰类,方法以及成员变量,当用在不同的场景下时具有不同的意义. 修饰类 如果修饰类,则代表这个类不可继承 修饰方法 如果修饰方法,则代表这个方法不可覆写:同时,允许 ...