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. ...
随机推荐
- Codeforces Round 504
(交互题真神奇,,,我自己瞎写了一发目测样例都没过去就AC了...) (只出了两题的竟然没掉下蓝名真是可怕) A:我的代码太不美观了,放个同学的(因为我是c++63分的蒟蒻所以根本不知道那些函数怎么用 ...
- python API whoami
import getpass print getpass.getuser() See the documentation of the getpass module. getpass.getuser( ...
- php(数组方法
什么是数组? 数组就是一组数据的集合 其表现形式就是内存中的一段连续的内存地址 数组名称其实就是连续内存地址的首地址 关于js中的数组特点 数组定义时无需指定数据类型 数组定义时可以无需指定数组长度 ...
- pandas 2
============== sdf={'rkey':[1,2,3,2],'name':['rkey1','rkey2','rkey3','rkey4']}sdf2={'lkey':[1,2,3],' ...
- Java ee第五周作业
Applet: Applet是采用Java编程语言编写的小应用程序,该程序可以包含在 HTML(标准通用标记语言的一个应用)页中,与在页中包含图像的方式大致相同. 含有Applet的网页的HTML文件 ...
- nodejs构建mock数据
Nodejs构建mock数据并通过rest api风格调用接口访问数据 如果我们只有json格式的数据文件,我们想通过访问url方式调用居然数据 确保电脑安装node环境 如果你没有安装好node环境 ...
- RoR-Scaffolding
Scaffolding能快速让rails跑起来 同时也生成JSON response rails g scaffolding "xxx" xxy:integer 生成scaffol ...
- 1、js比较日期的大小
① html <div class="ptb10"><span>共享开始时间:</span><input type="text& ...
- 2、Flutter 填坑记录篇
1.前言 之前写了一篇文章关于 flutter 初体验的一篇,https://www.cnblogs.com/niceyoo/p/9240359.html,当时一顿骚操作,然后程序就跑起来了. 隔了好 ...
- map函数和filter函数 zip函数
1.map函数 接收一个函数f和一个可迭代对象(列表,字典等),并通过把函数f依次作用在li每个元素上,得到一个新的list并返回 # -*-coding:utf8 -*- import reques ...