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. ...
随机推荐
- post数据过多时,有可能会丢失数据
开奖时,post时请求的user_id过多,导致活动id丢失
- [LeetCode] Clone Graph 克隆无向图
Given a reference of a node in a connected undirected graph, return a deep copy (clone) of the graph ...
- js字符串转数字(小数),数字转字符串
将字符串转化为小数并加法计算,然后保留两位小数 (parseFloat(that.data.pay_price) + parseFloat(that.data.qiandao)).toFixed(2) ...
- 【Java线程安全】 — ThreadLocal
[用法] 首先明确,ThreadLocal是用空间换时间来解决线程安全问题的,方法是各个线程拥有自己的变量副本. 既然如此,那么是涉及线程安全,必然有一个共享变量,我给大家声明一个: public c ...
- STL之pair对组
#include<iostream> #include<algorithm> #include<cstring> #include<cstdlib> u ...
- react子传父
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 解决mapper绑定异常:nested exception is org.apache.ibatis.binding.BindingException:
原因: 此异常的原因是由于mapper接口编译后在同一个目录下没有找到mapper映射文件而出现的.由于maven工程在默认情况下src/main/java目录下的mapper文件是不发布到targe ...
- Android开发网【申明:来源于网络】
Android开发网[申明:来源于网络] 地址:http://www.jizhuomi.com/android/video/
- findStr
目录 规则 目录结构 src/main.cpp src/findstr.cpp include/findstr.h ft/TestCase.cpp ft/makefile ftbuild.sh mai ...
- 环形dp
对于环形的dp 大多情况都是破环成链 例如 那道宝石手镯的环形 一般来说都是要破环成链的. 或者说 是 两次dp 一次断开 一次强制连接即可. 我想 我应该沉淀下来了这些天写的题都有点虚 要不就是看了 ...