• 大文件下载
    方案一:利用NSURLConnection和它的代理方法,及NSFileHandle(iOS9后不建议使用)
    相关变量:

    @property (nonatomic,strong) NSFileHandle *writeHandle;
    @property (nonatomic,assign) long long totalLength;

    1>发送请求

    // 创建一个请求
    NSURL *url = [NSURL URLWithString:@""];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    // 使用NSURLConnection发起一个异步请求
    [NSURLConnection connectionWithRequest:request delegate:self];

    2>在代理方法中处理服务器返回的数据

    /** 在接收到服务器的响应时调用下面这个代理方法
    1.创建一个空文件
    2.用一个句柄对象关联这个空文件,目的是方便在空文件后面写入数据
    */
    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(nonnull NSURLResponse *)response
    {
    // 创建文件路径
    NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject];
    NSString *filePath = [caches stringByAppendingPathComponent:@"videos.zip"]; // 创建一个空的文件到沙盒中
    NSFileManager *mgr = [NSFileManager defaultManager];
    [mgr createFileAtPath:filePath contents:nil attributes:nil]; // 创建一个用来写数据的文件句柄
    self.writeHandle = [NSFileHandle fileHandleForWritingAtPath:filePath]; // 获得文件的总大小
    self.totalLength = response.expectedContentLength;
    } /** 在接收到服务器返回的文件数据时调用下面这个代理方法
    利用句柄对象往文件的最后面追加数据
    */
    - (void)connection:(NSURLConnection *)connection didReceiveData:(nonnull NSData *)data
    {
    // 移动到文件的最后面
    [self.writeHandle seekToEndOfFile]; // 将数据写入沙盒
    [self.writeHandle writeData:data];
    } /**
    在所有数据接收完毕时,关闭句柄对象
    */
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection
    {
    // 关闭文件并清空
    [self.writeHandle closeFile];
    self.writeHandle = nil;
    }

    方案二:使用NSURLSession的NSURLSessionDownloadTask和NSFileManager

    NSURLSession *session = [NSURLSession sharedSession];
    NSURL *url = [NSURL URLWithString:@""];
    // 可以用来下载大文件,数据将会存在沙盒里的tmp文件夹
    NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    // location :临时文件存放的路径(下载好的文件) // 创建存储文件路径
    NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject];
    // response.suggestedFilename:建议使用的文件名,一般跟服务器端的文件名一致
    NSString *file = [caches stringByAppendingPathComponent:response.suggestedFilename]; /**将临时文件剪切或者复制到Caches文件夹
    AtPath :剪切前的文件路径
    toPath :剪切后的文件路径
    */
    NSFileManager *mgr = [NSFileManager defaultManager];
    [mgr moveItemAtPath:location.path toPath:file error:nil];
    }];
    [task resume];

    方案三:使用NSURLSessionDownloadDelegate的代理方法和NSFileManger

    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
    // 创建一个下载任务并设置代理
    NSURLSessionConfiguration *cfg = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:cfg delegate:self delegateQueue:[NSOperationQueue mainQueue]]; NSURL *url = [NSURL URLWithString:@""];
    NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url];
    [task resume];
    } #pragma mark -
    /**
    下载完毕后调用
    参数:lication 临时文件的路径(下载好的文件)
    */
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
    didFinishDownloadingToURL:(NSURL *)location{
    // 创建存储文件路径
    NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject];
    // response.suggestedFilename:建议使用的文件名,一般跟服务器端的文件名一致
    NSString *file = [caches stringByAppendingPathComponent:downloadTask.response.suggestedFilename]; /**将临时文件剪切或者复制到Caches文件夹
    AtPath :剪切前的文件路径
    toPath :剪切后的文件路径
    */
    NSFileManager *mgr = [NSFileManager defaultManager];
    [mgr moveItemAtPath:location.path toPath:file error:nil];
    } /**
    每当下载完一部分时就会调用(可能会被调用多次)
    参数:
    bytesWritten 这次调用下载了多少
    totalBytesWritten 累计写了多少长度到沙盒中了
    totalBytesExpectedToWrite 文件总大小
    */
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
    didWriteData:(int64_t)bytesWritten
    totalBytesWritten:(int64_t)totalBytesWritten
    totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
    // 这里可以做些显示进度等操作
    } /**
    恢复下载时使用
    */
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
    didResumeAtOffset:(int64_t)fileOffset
    expectedTotalBytes:(int64_t)expectedTotalBytes
    {
    // 用于断点续传
    }
  • 断点下载
    方案一:
    1>在方案一的基础上新增两个变量和按扭
    @property (nonatomic,assign) long long currentLength;
    @property (nonatomic,strong) NSURLConnection *conn;

    2>在接收到服务器返回数据的代理方法中添加如下代码

        // 记录断点,累计文件长度
    self.currentLength += data.length;

    3>点击按钮开始(继续)或暂停下载

    - (IBAction)download:(UIButton *)sender {
    
        sender.selected = !sender.isSelected;
    
        if (sender.selected) { // 继续(开始)下载
    NSURL *url = [NSURL URLWithString:@""];
    // ****关键点是使用NSMutableURLRequest,设置请求头Range
    NSMutableURLRequest *mRequest = [NSMutableURLRequest requestWithURL:url]; NSString *range = [NSString stringWithFormat:@"bytes=%lld-",self.currentLength];
    [mRequest setValue:range forHTTPHeaderField:@"Range"]; // 下载
    self.conn = [NSURLConnection connectionWithRequest:mRequest delegate:self];
    }else{
    [self.conn cancel];
    self.conn = nil;
    }
    }

    4>在接受到服务器响应执行的代理方法中第一行添加下面代码,防止重复创建空文件

     if (self.currentLength)  return;

    方案二:使用NSURLSessionDownloadDelegate的代理方法
    所需变量

    @property (nonatomic,strong) NSURLSession *session;
    @property (nonatomic,strong) NSData *resumeData; //包含了继续下载的开始位置和下载的url
    @property (nonatomic,strong) NSURLSessionDownloadTask *task;

    方法

    // 懒加载session
    - (NSURLSession *)session
    {
    if (!_session) {
    NSURLSessionConfiguration *cfg = [NSURLSessionConfiguration defaultSessionConfiguration];
    self.session = [NSURLSession sessionWithConfiguration:cfg delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    }
    return _session;
    } - (IBAction)download:(UIButton *)sender { sender.selected = !sender.isSelected;
    if (self.task == nil) { // 开始(继续)下载
    if (self.resumeData) { // 原先有数据则恢复
    [self resume];
    }else{
    [self start]; // 原先没有数据则开始
    }
    }else{ // 暂停
    [self pause];
    }
    } // 从零开始
    - (void)start{
    NSURL *url = [NSURL URLWithString:@""];
    self.task = [self.session downloadTaskWithURL:url];
    [self.task resume];
    } // 暂停
    - (void)pause{
    __weak typeof(self) vc = self;
    [self.task cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
    //resumeData : 包含了继续下载的开始位置和下载的url
    vc.resumeData = resumeData;
    vc.task = nil;
    }];
    } // 恢复
    - (void)resume{
    // 传入上次暂停下载返回的数据,就可以回复下载
    self.task = [self.session downloadTaskWithResumeData:self.resumeData];
    // 开始任务
    [self.task resume];
    // 清空
    self.resumeData = nil;
    } #pragma mark - NSURLSessionDownloadDelegate
    /**
    下载完毕后调用
    参数:lication 临时文件的路径(下载好的文件)
    */
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
    didFinishDownloadingToURL:(NSURL *)location{
    // 创建存储文件路径
    NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject];
    // response.suggestedFilename:建议使用的文件名,一般跟服务器端的文件名一致
    NSString *file = [caches stringByAppendingPathComponent:downloadTask.response.suggestedFilename]; /**将临时文件剪切或者复制到Caches文件夹
    AtPath :剪切前的文件路径
    toPath :剪切后的文件路径
    */
    NSFileManager *mgr = [NSFileManager defaultManager];
    [mgr moveItemAtPath:location.path toPath:file error:nil];
    } /**
    每当下载完一部分时就会调用(可能会被调用多次)
    参数:
    bytesWritten 这次调用下载了多少
    totalBytesWritten 累计写了多少长度到沙盒中了
    totalBytesExpectedToWrite 文件总大小
    */
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
    didWriteData:(int64_t)bytesWritten
    totalBytesWritten:(int64_t)totalBytesWritten
    totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
    // 这里可以做些显示进度等操作
    } /**
    恢复下载时使用
    */
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
    didResumeAtOffset:(int64_t)fileOffset
    expectedTotalBytes:(int64_t)expectedTotalBytes
    {
    }

iOS开发-大文件下载与断点下载思路的更多相关文章

  1. iOS开发网络篇—多线程断点下载

    iOS开发网络篇—多线程断点下载 说明:本文介绍多线程断点下载.项目中使用了苹果自带的类,实现了同时开启多条线程下载一个较大的文件.因为实现过程较为复杂,所以下面贴出完整的代码. 实现思路:下载开始, ...

  2. iOS开发网络篇之文件下载、大文件下载、断点下载

    from: http://www.jianshu.com/p/f65e32012f07

  3. iOS开发——网络篇——NSURLSession,下载、上传代理方法,利用NSURLSession断点下载,AFN基本使用,网络检测,NSURLConnection补充

    一.NSURLConnection补充 前面提到的NSURLConnection有些知识点需要补充 NSURLConnectionDataDelegate的代理方法有一下几个 - (void)conn ...

  4. iOS开发系列-文件下载

    小文件下载 NSURLConnection下载小文件 #import "ViewController.h" @interface ViewController ()<NSUR ...

  5. 使用NSURLSessionDownloadTask实现大文件下载-监听下载进度

    - 5.1 涉及知识点(1)创建NSURLSession并设置代理,通过NSURLSessionDownloadTask并以代理的方式来完成大文件的下载 //1.创建NSURLSession,设置代理 ...

  6. iOS开发大神必备的Xcode插件

    写在前面 工欲善其事,必先利其器,iOS开发中不仅要学会Xcode的基本操作,而且还得学会一些Xcode的使用技巧,如掌握常用的快捷键等,还有就是今天要说到的Xcode插件,下面我就为大家介绍几款开发 ...

  7. ios开发之网络数据的下载与上传

    要实现网络数据的下载与上传,主要有三种方式 > NSURLConnection  针对少量数据,使用“GET”或“POST”方法从服务器获取数据,使用“POST”方法向服务器传输数据; > ...

  8. 【iOS】Resumable Doanloads(断点下载)

    这里我们只讨论iOS平台下的通用app,我们可以自己写代码来实现resume downloads,解释如下. resume一个HTTP下载不难,但必须要理解一些关键的HTTP概念: entity ta ...

  9. 使用NSURLSessionDataTask实现大文件离线断点下载(完整)

    6.1 涉及知识点(1)关于NSOutputStream的使用 //1. 创建一个输入流,数据追加到文件的屁股上 //把数据写入到指定的文件地址,如果当前文件不存在,则会自动创建 NSOutputSt ...

随机推荐

  1. 转:ShellExecute函数与ShellExecuteEx函数

    ShellExecute函数 ShellExecute函数原型及參数含义例如以下: function ShellExecute(hWnd: HWND; Operation, FileName, Par ...

  2. 增加VMWare开机画面时间,来防止快速跳过而无法进入BIOS

    用记事本打开xx.vmx,在里面添加一行: bios.bootDelay = "30000" 意思是开机后,在开机画面里停留30秒.

  3. Ajax.ActionLink 用法

    Ajax.ActionLink 用法 Ajax 属性的ActionLink方法可以创建一个具有异步行为的锚标签. ActionLink方法的第一个参数指定了链接文本,第二个参数是要异步调用的操作的名称 ...

  4. C# & WPF 随手小记之一 ——初探async await 实现多线程处理

    嗯...我也是在园子待了不短时间的人了,一直以来汲取着园友的知识,感觉需要回馈什么. 于是以后有空我都会把一些小技巧小知识写下来,有时候可能会很短甚至很简单,但希望能帮到大家咯. 第一篇文章来说说as ...

  5. xquery

    XQuery 相对于 XML,等同于 SQL 相对于数据库.设计用来查询 XML 数据.- 不仅仅限于 XML 文件,还包括任何可以 XML 形态呈现的数据,包括数据库. FLWOR 是 " ...

  6. Robots惊恐记

    昨天发现在百度上搜索不到网站krely.cn的关键词(季小鱼),我记得之前的排名是第四位.到底是哪里的错误导致这个问题呢. 百度排名丢失,那么360会不会也出现同样的错误呢. 可以看到,360提示是我 ...

  7. 【xcode插件介绍】Alcatraz ----The package manager for Xcode

    对于许多iOS开发者而言,Alcatraz并不陌生,甚至是相当的喜闻乐见.Alcatraz是一款开源的Xcode包管理器,由Marin Usalj.Delisa Mason和Jurre Stender ...

  8. 【python】初识python的问题

    这两天利用晚上时间简单的了解了一下python语言,在Mac上和Windows上都安装了python,对比两个平台,还是发现在mac上体验比较好一点.安装的版本好像也不一样,语法还有点小区别.简单的对 ...

  9. D10

    =-=今天被dev-c++坑到死..简直 晚上准备怒装liunx.. T1:数论 一开始碰到的是T1的运算符优先问题吧..maybe..但是我加上括号了还是WA啊..后面把式子拆开写才A了..次奥 附 ...

  10. 如何本地测试例如QQ登录等第三方接口

    前言:现在基本是个网站就会集成第三方的一些接口,比如QQ登录.分享等等.但是在开发的时候,尤其是没有这方面经验的开发人员来说,调试流程时会显得迷茫,不知道怎么调试.这里就个人的这方面学习摸索做一个总结 ...