zoukankan      html  css  js  c++  java
  • 大文件下载--断点续传--NSURLConnection

    有了上一篇文章的铺垫直接上代码,下面是分析原理.

    //  ViewController.m
    //  大文件下载
    //  Created by apple on 15/11/11.
    //  Copyright © 2015年 LDSmallCat. All rights reserved.
    #import "ViewController.h"
    #import "DACircularProgressView.h"//进度条的第三方框架
    @interface ViewController ()<NSURLConnectionDataDelegate>
    //下载和暂停按钮
    @property (weak, nonatomic) IBOutlet UIButton *button;
    //用来写数据的文件句柄对象
    @property(nonatomic,strong) NSFileHandle *writeHandle;
    //文件的总大小.用已经下载的进度 除以 文件的总大小,做出进度条
    @property(nonatomic,assign) long long totalLength;
    //当前已经写入的文件大小.已经下载的,
    @property(nonatomic,assign) long long currentLength;
    ///链接对象
    @property (nonatomic, strong) NSURLConnection *conn;
    //进度条
    @property(nonatomic,weak) DACircularProgressView * circleView;
    @end
    @implementation ViewController
    - (void)viewDidLoad{
        [super viewDidLoad];
    }
    - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
        NSLog(@"didFailWithError");
    }
    //接收到响应就会调用
    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
        //下载完成后 再次点击的时候,如果为1就直接返回,不在下载,或弹框告诉用户已经存在,
        //需要将self.currentLength写入本地文件才能做到不会重复下载.就是说这个程序无法避免重复下载
        if (self.currentLength) return;
        //数据保存的路径
        NSString * caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
        NSString * filepath = [caches stringByAppendingPathComponent:@"download2.mp4"];
        //通过这个路径创建一个文件  到 沙盒中
        NSFileManager * mgr = [NSFileManager defaultManager];
        [mgr createFileAtPath:filepath contents:nil attributes:nil];
        //创建一个用来写入文件数据的文件句柄
        self.writeHandle = [NSFileHandle fileHandleForWritingAtPath:filepath];
        //获取文件总大小
        self.totalLength = response.expectedContentLength;
        NSLog(@"didReceiveResponse文件总大小%lld",self.totalLength);
    }
    //接受到数据就会调用,如果数据很大会被调用多次.边下边存储到沙盒,不会有内存问题
    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
        //移动到文件的最后面
        [self.writeHandle seekToEndOfFile];
        //数据写入沙盒
        [self.writeHandle writeData:data];
        //累计文件长度,通过循环不断增大这个值,在下面的方法中拿到这个值量化去下载任务
        //比如这里第一次拿到300字节,下面请求下载0-300的任务,下次拼接后为1000,下面请求下载300-1000
        //的任务,
        self.currentLength += data.length;
        self.circleView.progress = (double)self.currentLength / self.totalLength;
        //经过不断拼接,已经写入的数据,
        NSLog(@"didReceiveData   已经下载的数据%lld   ",self.currentLength);
    }
    //下载完成后调用,做些处理工作
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection{
        //变量归零
        self.currentLength = 1;
        self.totalLength = 0;
        //关闭文佳
        [self.writeHandle closeFile];
        self.writeHandle = nil;
    }
    - (IBAction)downLoad:(UIButton *)sender{
        //状态取反
        sender.selected = ! sender.selected;
        //断点续传,断点下载
        if(sender.selected){
            //1.点击下载,创建URL,发送请求.url中不能有中文
            NSURL * url = [NSURL URLWithString:@"http://localhost/dawenjianyasuo.zip"];
            //2.请求
            NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];
            self.currentLength = 0;
            //设置请求头.实现的要点在这里,此处的Rang属性实现了下载的控制,用self.currentLength
            //来保存已经下载了多少字节,
            NSString * range = [NSString stringWithFormat:@"bytes=%lld-",self.currentLength];
            [request setValue:range forHTTPHeaderField:@"Range"];
            //下载(创建完conn对象后,会自动发起一个异步请求)

    self.conn = [NSURLConnection connectionWithRequest:request delegate:self]; }else{//一旦点击暂停创建的request就会销毁,再次点击下载时需要重新创建. [self.conn cancel]; self.conn = nil; } } @end

    整体流程:

    原理会在下一篇文章中说明,

  • 相关阅读:
    WSGI 简介
    past.deploy
    python中self和cls
    heat template例子
    cinder-api 启动过程学习
    ubuntu安装cloud-init制作成openstack镜像---cloud-init篇
    sus 11.3如何安装与配置cloud-init
    DHCP工作原理
    交换
    路由器
  • 原文地址:https://www.cnblogs.com/LDSmallCat/p/4957483.html
Copyright © 2011-2022 走看看