最近在做一个小项目的时候,发现使用NSURLSession或者AFNNetworking进行断点续传时诸多的不便,于是自己封装了一个类来实现断点续传,在程序重新启动时仍然可以继续下载(需自己调用方法),同时可以在同一时间多次调用该类方法。使用时请注意传入各参数的合理性,方法内部并没有对传入的参数进行修正

主要技术: NSURLConnection、block、NFFileHandle

1、首先,我提供一个类方法,供外界调用。 创建的类名为DownloadService

 //
// DownloadService.h
// 11111
//
// Created by Liu Feng on 14-2-17.
// Copyright (c) 2014年 Liu Feng. All rights reserved.
// #import <Foundation/Foundation.h> typedef void (^DownloadServiceSuccess)(NSString *savePath);
typedef void (^DownloadServiceFailure)(NSError *error); @interface DownloadService : NSObject
/**
* 下载指定URL的资源到路径
*
* @param urlStr 网络资源路径
* @param toPath 本地存储文件夹
* @param capacity 缓存大小,单位为Mb
* @param success 成功时回传本地存储路径
* @param failure 失败时回调的错误原因
*/
+ (void)downLoadWithURL:(NSString *)urlStr toDirectory:(NSString *)toDirectory cacheCapacity:(NSUInteger)capacity success:(DownloadServiceSuccess)success failure:(DownloadServiceFailure)failure; @end

2、在.m中实现

 //
// DownloadService.m
// 11111
//
// Created by Liu Feng on 14-2-17.
// Copyright (c) 2014年 Liu Feng. All rights reserved.
// #import "DownloadService.h" static DownloadService *_download;
static NSMutableDictionary *_dictPath;
static NSMutableDictionary *_dictBlock;
static NSMutableDictionary *_dictHandle;
static unsigned long long _cacheCapacity; // 缓存
static NSMutableData *_cacheData; typedef void (^myBlcok)(NSString *savePath, NSError *error); @interface DownloadService ()<NSURLConnectionDataDelegate> @end @implementation DownloadService + (void)initialize
{
_download = [[DownloadService alloc] init];
_dictPath = [NSMutableDictionary dictionary]; // 存储文件路径
_dictBlock = [NSMutableDictionary dictionary]; // 存储block
_dictHandle = [NSMutableDictionary dictionary]; // 存储NSFileHandle对象
_cacheData = [NSMutableData data]; // 存放缓存
} + (void)downLoadWithURL:(NSString *)urlStr toDirectory:(NSString *)toDirectory cacheCapacity:(NSInteger)capacity success:(DownloadServiceSuccess)success failure:(DownloadServiceFailure)failure{ // 1. 创建文件
NSString *fileName = [urlStr lastPathComponent];
NSString *filePath = [NSString stringWithFormat:@"%@/%@", toDirectory, fileName]; // 记录文件起始位置
unsigned long long from = ;
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]){ // 已经存在
from = [[NSData dataWithContentsOfFile:filePath] length];
}else{ // 不存在,直接创建
[[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];
} // url
NSURL *url = [NSURL URLWithString:urlStr]; // 请求
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:5.0f]; // 设置请求头文件
NSString *rangeValue = [NSString stringWithFormat:@"bytes=%llu-", from];
[request addValue:rangeValue forHTTPHeaderField:@"Range"]; // 创建连接
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:_download]; // 保存文章连接
_dictPath[connection.description] = filePath; // 保存block,用于回调
myBlcok block = ^(NSString *savePath, NSError *error){
if (error) {
if (failure) {
failure(error);
}
}else{
if (success) {
success(savePath);
}
}
};
_dictBlock[connection.description] = block; // 保存缓存大小
_cacheCapacity = capacity * * ; // 开始连接
[connection start];
}
/**
* 接收到服务器响应
*
* @param connection 哪一个连接
* @param response 响应对象
*/
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// 取出文章地址
NSString *filePath = _dictPath[connection.description]; // 打开文件准备输入
NSFileHandle *outFile = [NSFileHandle fileHandleForWritingAtPath:filePath]; // 保存文件操作对象
_dictHandle[connection.description] = outFile;
}
/**
* 开始接收数据
*
* @param connection 哪一个连接
* @param data 二进制数据
*/
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// 取出文件操作对象
NSFileHandle *outFile = _dictHandle[connection.description]; // 移动到文件结尾
[outFile seekToEndOfFile]; // 保存数据
[_cacheData appendData:data]; if (_cacheData.length >= _cacheCapacity) {
// 写入文件
[outFile writeData:data]; // 清空数据
[_cacheData setLength:];
}
}
/**
* 连接出错
*
* @param connection 哪一个连接出错
* @param error 错误信息
*/
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
// 取出文件操作对象
NSFileHandle *outFile = _dictHandle[connection.description]; // 关闭文件操作
[outFile closeFile]; // 回调block
myBlcok block = _dictBlock[connection.description]; if (block) {
block(nil, error);
} // 移除字典中
[_dictHandle removeObjectForKey:connection.description];
[_dictPath removeObjectForKey:connection.debugDescription];
[_dictBlock removeObjectForKey:connection.description];
}
/**
* 结束加载
*
* @param connection 哪一个连接
*/
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// 取出文件操作对象
NSFileHandle *outFile = _dictHandle[connection.description]; // 关闭文件操作
[outFile closeFile]; // 取出路径
NSString *savePath = [_dictPath objectForKey:connection.description]; // 取出block
myBlcok block = _dictBlock[connection.description]; // 回调
if (block) {
block(savePath, nil);
} // 移除字典中
[_dictHandle removeObjectForKey:connection.description];
[_dictPath removeObjectForKey:connection.debugDescription];
[_dictBlock removeObjectForKey:connection.description];
} @end

iOS开发网络编程之断点续传-NSURLConnection的更多相关文章

  1. IOS开发——网络编程总汇

    关于IOS的网络编程,大家都会想到C实现的底层BSD ,CFNetwork和NSURL之类的库,虽然如今非常多第三方库非常方便,可是作为一名开发人员,也须要了解底层代码. 以下的思维导图是关于眼下开发 ...

  2. ios开发 网络编程浅析(一)

    iphone包含了很多框架和库,从底层的套接字到不同层次的封装,可以方便地给程序添加网络功能. (1)BSD套接字.最底层的套接字,这是Unix网络开发常用的API.如果从其他系统移植程序,而程序用的 ...

  3. iOS开发——网络编程Swift篇&Alamofire详解

    Alamofire详解 预览图 Swift Alamofire 简介 Alamofire是 Swift 语言的 HTTP 网络开发工具包,相当于Swift实现AFNetworking版本. 当然,AF ...

  4. iOS开发——网络编程OC篇&(一)XMPP简单介绍与准备

    XMPP简单介绍与准备 一.即时通讯简单介绍 1.简单说明 即时通讯技术(IM)支持用户在线实时交谈.如果要发送一条信息,用户需要打开一个小窗口,以便让用户及其朋友在其中输入信息并让交谈双方都看到交谈 ...

  5. iOS开发——网络编程OC篇&Socket编程

    Socket编程 一.网络各个协议:TCP/IP.SOCKET.HTTP等 网络七层由下往上分别为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. 其中物理层.数据链路层和网络层通常被称作 ...

  6. iOS开发——网络编程OC篇&使用WebView构建HyBird应用

    使用WebView构建HyBird应用 HyBird是一种本地技术与Web相结合,能过实现跨平台的移动应用开发,最常用的一个框架:PhoneGap 一:首先,写好html代码 <!DOCTYPE ...

  7. iOS开发——网络编程Swift篇&(二)同/异&步请求

    同/异&步请求 同步: // MARK: - 同步请求 func httpSynchronousRequest() { //创建NSURL对象 var url:NSURL! = NSURL(s ...

  8. iOS开发——网络编程Swift篇&(八)SwiftyJSON详解

    SwiftyJSON详解 最近看了一些网络请求的例子,发现Swift在解析JSON数据时特别别扭,总是要写一大堆的downcast(as?)和可选(Optional),看?号都看花了.随后发现了这个库 ...

  9. ios开发网络学习三:NSURLConnection小文件大文件下载

    一:小文件下载 #import "ViewController.h" @interface ViewController ()<NSURLConnectionDataDele ...

随机推荐

  1. TouchAndGuest触摸事件和手势

    ////  nextViewController.m#import "nextViewController.h"#import "my.h"@interface ...

  2. 20150515--关于IIS的备忘(WIN7)

    一.IIS服务位置: 1)控制面板--程序和功能 2)点击打开或关闭Windows功能, 3)Internet服务信息(英文:internet information services)--Web管理 ...

  3. GForms展现服务云开发平台

    GForms完全基于开放标准,使用XForms作为面向服务的架构简单易用的前端,帮助用户跨多个行业加速数据整合.GForms提供可视化设计器,实现展现服务开发中数据与模型完全分离,加快开发速度快速投入 ...

  4. Ueditor 1.4.3 单独调用上传图片,或文件功能

    第一步, 引入文件 <script src="ueditor/ueditor.config.js" type="text/javascript" char ...

  5. php验证字符串是否以逗号隔开包括中文字符串

    if(preg_match('/^[\x{4e00}-\x{9fa5}\w]+(,[\x{4e00}-\x{9fa5}\w]+)*$/u','体育,娱乐')){ echo 'ok';}

  6. python 中range与xrange的区别

    先来看看range与xrange的用法介绍 help(range)Help on built-in function range in module __builtin__: range(...) r ...

  7. MySQL中,把varchar类型转为date类型

    如下表: 先使用str_to_date函数,将其varchar类型转为日期类型,然后从小到大排序 语法:select str_to_date(class_time,'%Y%m%d %H:%i:%s') ...

  8. LR通过SiteScope监控mysql

    SiteScope下载,安装 要想使用LoadRunner监测MySQL数据库的性能,LoadRunner没有提供直接监测 MySQL的功能,所以,我们需要借助sitescope监控,然后在LoadR ...

  9. JavaScript 中的 replace 方法

    定义和用法 replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串. stringObject.replace(regexp/substr,replaceme ...

  10. sql server 查询多个不关联表且对结果编号

    1.除非另外还指定了 TOP 或 FOR XML,否则,ORDER BY 子句在视图.内联函数.派生表.子查询和公用表表达式中无效. 解决方法:top 100 percent * 2.如何对查询结果编 ...