一、传统的下载文件的方式  

- (void)downloaderWithUrl:(NSURL *)url
{
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {

        if (!connectionError)
        {
            NSHTTPURLResponse *urlResponse = (NSHTTPURLResponse *)response;
            if (urlResponse.statusCode == 200 || urlResponse.statusCode == 304)
            {
                [data writeToFile:@"/Users/gxiangzi/Desktop/a.mp4" atomically:YES];
                NSLog(@"OK");
            }
        }else
        {
            NSLog(@"错误");
        }
    }];
}

但是这种方式存在着弊端:

  1> 用不无法跟踪下载的进度,无法直观的显示下载进度

  2> 文件下载的时候,都会先下载到内存之中,导致内存 > 所需文件的大小长度,会造成程序崩溃等现象(可以查看内存的耗费)

二、代理的方式下载程序(NSURLConnectionDownloadDelegate)

#import "GXDownloader.h"

@interface GXDownloader () <NSURLConnectionDownloadDelegate>

@end

@implementation GXDownloader

- (void)downloaderWithUrl:(NSURL*)url
{
    NSURLRequest* request = [NSURLRequest requestWithURL:url];
    [[NSURLConnection alloc] initWithRequest:request delegate:self];
}

#pragma mark - NSURLConnectionDownloadDelegate

/**
 bytesWritten: 表示下载的数据字节数
 totalBytesWritten:总的已经下载的字节数
 expectedTotalBytes:期望的总的字节数
 */
- (void)connection:(NSURLConnection*)connection didWriteData:(long long)bytesWritten totalBytesWritten:(long long)totalBytesWritten expectedTotalBytes:(long long)expectedTotalBytes
{
    float progress = (float)totalBytesWritten / expectedTotalBytes;
    NSLog(@"%f", progress);
}

/**
 *  @param connection
 *  @param totalBytesWritten : 总的已经下载的字节数
 *  @param expectedTotalBytes : 期望总的字节数
 */
- (void)connectionDidResumeDownloading:(NSURLConnection*)connection totalBytesWritten:(long long)totalBytesWritten expectedTotalBytes:(long long)expectedTotalBytes
{
}

/**
 *  @param connection
 *  @param destinationURL:下载完的目标路径
 */
- (void)connectionDidFinishDownloading:(NSURLConnection*)connection destinationURL:(NSURL*)destinationURL
{
    NSLog(@"%@", destinationURL);
}

优点:

  1> 该种方式可以跟踪文件下载的进度;

  2> 也可以解决内存消耗过大的问题

弊端:  这丫的 下载的文件没有 ,就是虽然你显示下载完成,但是你本地找不到该文件------没有任何卵用

三、第三种方式--代理(NSURLConnectionDataDelegate)

//
//  GXDownloader.m
//  02-下载
//
//  Created by gxiangzi on 15/8/21.
//  Copyright (c) 2015年 hqu. All rights reserved.
//

#import "GXDownloader.h"

@interface GXDownloader () <NSURLConnectionDataDelegate>

// 文件的总长度
@property (nonatomic, assign) long long expectedContentLength;

// 已经接受到文件的长度
@property (nonatomic, assign) long long receivedContentLength;

// 已经接收到的文件的总长度
@property (nonatomic, strong) NSMutableData* receivedData;

@end

@implementation GXDownloader

- (void)downloaderWithUrl:(NSURL*)url
{
    NSURLRequest* request = [NSURLRequest requestWithURL:url];
    [[NSURLConnection alloc] initWithRequest:request delegate:self];
}

#pragma mark - NSURLConnectionDataDelegate

/**
 *  已经接受到响应头
 */
- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response
{
    self.expectedContentLength = response.expectedContentLength;
}

/**
 *  文件接受到一点的时候就是用
 */
- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data
{
    // 把二进制数据进行拼接
    [self.receivedData appendData:data];
    // 拼接长度
    self.receivedContentLength += data.length;

    float progress = (float)self.receivedContentLength / self.expectedContentLength;

    NSLog(@"下载进度: %.2f",progress);

}

/**
 *  下载出错的时候调用
 */
- (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
{
}

/**
 *  当下载完成的时候调用
 */
- (void)connectionDidFinishLoading:(NSURLConnection*)connection
{
    NSLog(@"下载完成");

    // IOS 的文件路径,只能讲软件操作的数据放在沙盒内
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    NSString *fileName = [path stringByAppendingPathComponent:@"love.mp4"];

    NSLog(@"%@",fileName);

    [self.receivedData writeToFile:fileName atomically:YES];

}

#pragma mark -懒加载
- (NSMutableData*)receivedData
{
    if (!_receivedData) {
        _receivedData = [NSMutableData data];
    }
    return _receivedData;
}

@end

优点:

  1> 可以检测到进度的问题

  2> 文件的写入的路径之中,文件可以存在

弊端:

  占用的内存太大  

为了解决上面的问题: 引入了NSHandle  和 NSOutputStream ------下一点 写入文件一点

四、NSHandle的使用

//
//  GXDownloader.m
//  02-下载
//
//  Created by gxiangzi on 15/8/21.
//  Copyright (c) 2015年 hqu. All rights reserved.
//

#import "GXDownloader.h"

@interface GXDownloader () <NSURLConnectionDataDelegate>

// 文件的总长度
@property (nonatomic, assign) long long expectedContentLength;

// 已经接受到文件的长度
@property (nonatomic, assign) long long receivedContentLength;

@end

@implementation GXDownloader

- (void)downloaderWithUrl:(NSURL*)url
{
    NSURLRequest* request = [NSURLRequest requestWithURL:url];
    [[NSURLConnection alloc] initWithRequest:request delegate:self];
}

#pragma mark - NSURLConnectionDataDelegate

/**
 *  已经接受到响应头
 */
- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response
{
    self.expectedContentLength = response.expectedContentLength;
}

/**
 *  文件接受到一点的时候就是用
 */
- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data
{
    // 拼接长度
    self.receivedContentLength += data.length;

    float progress = (float)self.receivedContentLength / self.expectedContentLength;
    NSLog(@"%f",progress);

    NSString* path = @"/Users/gxiangzi/Desktop/a.mp4";

    NSFileHandle* handle = [NSFileHandle fileHandleForWritingAtPath:path];
    // 如果handle  不会帮我们创建文件
    if (handle == nil) {
        [data writeToFile:path atomically:YES];
    }
    else {
        //让offset指向文件的末尾,在末尾处追加数据
        [handle seekToEndOfFile];
        //写输入
        [handle writeData:data];
        //关闭  (等文件下载完成关闭更好)
        [handle closeFile];
    }

}

/**
 *  当下载完成的时候调用
 */
- (void)connectionDidFinishLoading:(NSURLConnection*)connection
{
    NSLog(@"下载完成");
}

@end

原理:下载一点数据 写一点数据

效果:能够达到占用很少内存

五、NSOutputStream的使用

//
//  GXDownloader.m
//  02-下载
//
//  Created by gxiangzi on 15/8/21.
//  Copyright (c) 2015年 hqu. All rights reserved.
//

#import "GXDownloader.h"

@interface GXDownloader () <NSURLConnectionDataDelegate>

// 文件的总长度
@property (nonatomic, assign) long long expectedContentLength;

// 已经接受到文件的长度
@property (nonatomic, assign) long long receivedContentLength;

@property (nonatomic, strong) NSOutputStream* stream;

@end

@implementation GXDownloader

- (void)downloaderWithUrl:(NSURL*)url
{
    NSURLRequest* request = [NSURLRequest requestWithURL:url];
    [[NSURLConnection alloc] initWithRequest:request delegate:self];
}

#pragma mark - NSURLConnectionDataDelegate

/**
 *  已经接受到响应头
 */
- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response
{
    self.expectedContentLength = response.expectedContentLength;

    NSString* path = @"/Users/gxiangzi/Desktop/a.mp4";

    // 注意 此处的url 为本地的路径
    // 前面加 file:// 无效
    // 只能使用 [NSURL fileURLWithPath:path]
   self.stream = [NSOutputStream outputStreamWithURL:[NSURL fileURLWithPath:path] append:YES];

    [self.stream open];

}

/**
 *  文件接受到一点的时候就是用
 */
- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data
{
    // 拼接长度
    self.receivedContentLength += data.length;

    float progress = (float)self.receivedContentLength / self.expectedContentLength;
    NSLog(@"%f", progress);

    [self.stream write:data.bytes maxLength:data.length];
}

/**
 *  当下载完成的时候调用
 */
- (void)connectionDidFinishLoading:(NSURLConnection*)connection
{
    NSLog(@"下载完成");
    [self.stream close];
}

- (NSOutputStream *)stream
{
    if (_stream == nil)
    {
        _stream = [[NSOutputStream alloc] init];
    }
    return _stream;
}

@end

【待整理】IOS开发之下载的更多相关文章

  1. 整理iOS开发常用的第三方资源

    一:第三方插件 1:基于响应式编程思想的oc 地址:https://github.com/ReactiveCocoa/ReactiveCocoa 2:hud提示框 地址:https://github. ...

  2. [整理]iOS开发学习

    最近想趁着休假,花点时间了解下最新的iOS8下的新特性以及Swift语言(想大致了解下和Objective-C有了哪些改进和不同) 可以通过Chris Lattner:Swift 编程语言首席架构师初 ...

  3. 李洪强iOS开发之下载

    // // //  LHQDownLoader.m //  A21 - 李洪强 - 下载 // //  Created by vic fan on 16/7/3. //  Copyright © 20 ...

  4. iOS开发--网络下载

    这里使用的是NSURLConnection的代理请求下载,并且是具有进度,UI能实时刷新,至于NSURLConnection如何请求.并且有几种请求方法请看NSURLConnection请求简介,在这 ...

  5. IOS开发-phonegap及免证书及真机调试

    回头补记(Last edited at 2015.5.24). 第一步:建立项目 参见:Xcode5 + phoneGap2.9搭建ios开发环境 下载phonegap2.9.1,解压. 命令行,进入 ...

  6. 文顶顶iOS开发博客链接整理及部分项目源代码下载

    文顶顶iOS开发博客链接整理及部分项目源代码下载   网上的iOS开发的教程很多,但是像cnblogs博主文顶顶的博客这样内容图文并茂,代码齐全,示例经典,原理也有阐述,覆盖面宽广,自成系统的系列教程 ...

  7. 【热门收藏】iOS开发人员必看的精品资料(100个)——下载目录

    iPhone.iPad产品风靡全球,巨大的用户群刺激着iOS软件开发需求,然而国内人才缺口很大,正处于供不应求的状态,ios开发前景大好.我们整理了51CTO下载中心100份热门的ios开发资料,做了 ...

  8. iOS 开发设计常用软件及工具整理

    1, xCode 2, AppCode 3, Skech 原型设计软件 4, Hype 动画设计工具 5, fontawsome 免费图表 6, Prepo icon, images.catlog 生 ...

  9. iOS开发使用半透明模糊效果方法整理

    虽然iOS很早就支持使用模糊效果对图片等进行处理,但尤其在iOS7以后,半透明模糊效果得到大范围广泛使用.包括今年最新发布的iOS8也沿袭了这一设计,甚至在OS X 10.10版Yosemite中也开 ...

随机推荐

  1. js 日常问题记录

    1.解决ie6下css背景图不缓存 try{ document.execCommand('BackgroundImageCache',false,true); }catch(e){} 2.为ajax设 ...

  2. 用 C 语言编写 Windows 服务程序的五个步骤

    Windows 服务被设计用于需要在后台运行的应用程序以及实现没有用户交互的任务.为了学习这种控制台应用程序的基础知识,C(不是C++)是最佳选择.本文将建立并实现一个简单的服务程序,其功能是查询系统 ...

  3. N年之后,只记得三井寿!而我们程序猿们也要加油珍惜时间!

    [感觉程序员看一篇励志文章效果大于6篇技术文章,3份源码下载.....所以上此文] [说明:本文不少段落是摘自别人文章,因为本人写程序的文笔有限,怕感动不了大家,所以摘取了不错的部分] 前段时间重新看 ...

  4. 解决Sqlite UTF-8中文数据格式在DOS窗口下中文乱码

    问题如下图所示: 右键查看DOS属性:点击选项->当前代码页为GBK 只要将当前代码页编码值设置为UTF-8就可以了: ‘退出sqlite:.exit 输入:chcp 65001回车 右键属性: ...

  5. spoj 104 Highways (最小生成树计数)

    题目链接:http://www.spoj.pl/problems/HIGH/ 题意:求最小生成树个数. #include<algorithm> #include<cstdio> ...

  6. Qt编程之实现在QFileDialog上添加自定义的widget

    上网搜索找到的方法如下: http://www.qtforum.org/article/20841/how-to-add-a-qwidget-in-qfiledialog.html#post78422 ...

  7. mysql 的 decimal类型

    最近做项目时将decimal定义成了decimal(5,2),然后等到最大的结果都是999.99,找了很多地方找不出bug在哪里插入很更新的数据都是正确的而结果却都是999.99,最后才知道decim ...

  8. HDU 5418 Victor and World (Floyd + 状态压缩DP)

    题目大意:从起点 1 开始走遍所有的点,回到起点 1 ,求出所走的最短长度. 思路:首先利用 Floyed 求出任意两点之间的最短距离 dis[i][j].求出任意两点之间的最短距离后,运用动态规划. ...

  9. CF 545E Paths and Trees

    题目大意:给出n个点,m条无向边,每条边有长度.求一棵树,要求树上的每个点到源点距离最小的前提下,使得树上的边的长度和最小.输出树上边的总长度,以及树上的边的序号(按输入顺序 1...m). 思路 : ...

  10. Java vs Python

    面试时常问到这两种语言的区别,在此总结一下. Referrence: Udemy:python-vs-java Generally, Python is much simpler to use, an ...