一 实现如下效果


 

二 实现代码


 //
// 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实现简单的断点下载的更多相关文章

  1. iOS开发网络篇—简单介绍ASI框架的使用

    iOS开发网络篇—简单介绍ASI框架的使用 说明:本文主要介绍网络编程中常用框架ASI的简单使用. 一.ASI简单介绍 ASI:全称是ASIHTTPRequest,外号“HTTP终结者”,功能十分强大 ...

  2. iOS开发之常用第三方框架(下载地址,使用方法,总结)

    iOS开发之常用第三方框架(下载地址,使用方法,总结) 说句实话,自学了这么久iOS,如果说我不知道的但是又基本上都摸遍了iOS相关知识,但是每次做项目的时候,遇到难一点的地方或者没试过的东西就闷了. ...

  3. iOS开发UI篇—简单的浏览器查看程序

    iOS开发UI篇—简单的浏览器查看程序 一.程序实现要求 1.要求 2. 界面分析 (1) 需要读取或修改属性的控件需要设置属性 序号标签 图片 图片描述 左边按钮 右边按钮 (2) 需要监听响应事件 ...

  4. iOS开发UI篇—简单介绍静态单元格的使用

    iOS开发UI篇—简单介绍静态单元格的使用 一.实现效果与说明 说明:观察上面的展示效果,可以发现整个界面是由一个tableview来展示的,上面的数据都是固定的,且几乎不会改变. 要完成上面的效果, ...

  5. iOS开发Swift篇—简单介绍

    iOS开发Swift篇—简单介绍 一.简介 Swift是苹果于2014年WWDC(苹果开发者大会)发布的全新编程语言 Swift在天朝译为“雨燕”,是它的LOGO 是一只燕子,跟Objective-C ...

  6. 李洪强iOS开发之- 实现简单的弹窗

     李洪强iOS开发之- 实现简单的弹窗 实现的效果:  112222222222223333333333333333

  7. IOS开发苹果官方Sample Code及下载地址

    IOS开发苹果官方Sample Code及下载地址 在线浏览地址:https://developer.apple.com/library/ios/navigation/#section=Resourc ...

  8. iOS开发笔记,简单实现视频音频的边下边播

    总是在网上看别人的博文,受益匪浅,从没自己写过,今天分享一点小经验,第一次写技术博客,希望对同行的ios猿们有所帮助.   先介绍一下自己的情况:一年ios开发,http协议不太懂,大约知道断点下载h ...

  9. ios网络 -- HTTP请求 and 文件下载/断点下载

    一:请求 http://www.jianshu.com/p/8a90aa6bad6b 二:下载 iOS网络--『文件下载.断点下载』的实现(一):NSURLConnection http://www. ...

随机推荐

  1. Codeforces Round 504

    (交互题真神奇,,,我自己瞎写了一发目测样例都没过去就AC了...) (只出了两题的竟然没掉下蓝名真是可怕) A:我的代码太不美观了,放个同学的(因为我是c++63分的蒟蒻所以根本不知道那些函数怎么用 ...

  2. python API whoami

    import getpass print getpass.getuser() See the documentation of the getpass module. getpass.getuser( ...

  3. php(数组方法

    什么是数组? 数组就是一组数据的集合 其表现形式就是内存中的一段连续的内存地址 数组名称其实就是连续内存地址的首地址 关于js中的数组特点 数组定义时无需指定数据类型 数组定义时可以无需指定数组长度 ...

  4. pandas 2

    ============== sdf={'rkey':[1,2,3,2],'name':['rkey1','rkey2','rkey3','rkey4']}sdf2={'lkey':[1,2,3],' ...

  5. Java ee第五周作业

    Applet: Applet是采用Java编程语言编写的小应用程序,该程序可以包含在 HTML(标准通用标记语言的一个应用)页中,与在页中包含图像的方式大致相同. 含有Applet的网页的HTML文件 ...

  6. nodejs构建mock数据

    Nodejs构建mock数据并通过rest api风格调用接口访问数据 如果我们只有json格式的数据文件,我们想通过访问url方式调用居然数据 确保电脑安装node环境 如果你没有安装好node环境 ...

  7. RoR-Scaffolding

    Scaffolding能快速让rails跑起来 同时也生成JSON response rails g scaffolding "xxx" xxy:integer 生成scaffol ...

  8. 1、js比较日期的大小

    ① html <div class="ptb10"><span>共享开始时间:</span><input type="text& ...

  9. 2、Flutter 填坑记录篇

    1.前言 之前写了一篇文章关于 flutter 初体验的一篇,https://www.cnblogs.com/niceyoo/p/9240359.html,当时一顿骚操作,然后程序就跑起来了. 隔了好 ...

  10. map函数和filter函数 zip函数

    1.map函数 接收一个函数f和一个可迭代对象(列表,字典等),并通过把函数f依次作用在li每个元素上,得到一个新的list并返回 # -*-coding:utf8 -*- import reques ...