AFNetworking的版本:
platform:ios,'7.0'

pod "AFNetworking","~> 2.3.0"

简单思路:通过重组progressBlock , successBlock ,requestUrl ,outPutStream,然后利用AFNetworking自带的pause,resume即可妥妥的实现。

不过碰到了一些问题也挺折磨人的,文件输入流,初始化就碰到问题了,
1.[self.requestOperation setOutputStream:[NSOutputStream outputStreamToFileAtPath:self.cachePath() append:YES]
如果追加了原始文件的data,就无法在下载过程中从outPutStream中获取到data。
 [self.requestOperation setOutputStream:[NSOutputStream outputStreamToFileAtPath:self.cachePath() append:NO]
如果不追加,续传就成覆盖了。

官方文档也没仔细看,所幸就使用不追加的方式,然后手动同步文件与输入流。 方法如下

-(void)readCacheToOutStreamWithPath:(NSString*)path;

2.pause之后,AFHTTPRequestOperation.totalBytesRead,仍然记录这之前的读取长度,如果resume了,这是content-length发生了变法,这个时候就需要从组progressBlock了,同时也需要将totalBytesRead设为0,因为是私有属性,所以就用KVC。

[self.requestOperation setValue:@"0" forKey:@"totalBytesRead"];

 
 
------------随便贴个VC----------------------
 

- (IBAction)download:(id)sender

{

//http://202.102.88.133/youku/657114D0FE44481C592F964ABD/030020010053F4AB5FB92A01296A84C7E5A401-0FC6-BD65-4525-706B419E9EA6.mp4

//    http://b.hiphotos.baidu.com/image/h%3D1200%3Bcrop%3D0%2C0%2C1920%2C1200/sign=b284ea7541a98226a7c12f25bab28262/960a304e251f95ca8888fab6cb177f3e670952b4.jpg

NSString* path = [NSHomeDirectory()stringByAppendingPathComponent:@"Documents/temp"];

NSLog(@"path = %@",path);

operation = [[DownLoadOperationalloc] init];

[operationdownloadWithUrl:Picture

cachePath:^NSString *{

return path;

} progressBlock:^(NSUInteger bytesRead,long long totalBytesRead,long long totalBytesExpectedToRead) {

NSLog(@"bytesRead = %u ,totalBytesRead = %llu totalBytesExpectedToRead = %llu",bytesRead,totalBytesRead,totalBytesExpectedToRead);

float progress = totalBytesRead / (float)totalBytesExpectedToRead;

[self.progressViewsetProgress:progressanimated:YES];

[self.labelsetText:[NSStringstringWithFormat:@"%.2f%%",progress*100]];

UIImage* image = [UIImageimageWithData:operation.requestOperation.responseData];

[self.imageViewsetImage:image];

} success:^(AFHTTPRequestOperation *operation,id responseObject) {

NSLog(@"success");

//                         UIImage* image = [UIImage imageWithData:operation.responseData];

//                         [self.imageView setImage:image];

} failure:^(AFHTTPRequestOperation *operation,NSError *error) {

NSLog(@"error = %@",error);

}];

}

 
 
----------------------------------
 
 
 
 
 
 

#import <Foundation/Foundation.h>

#import "AFNetworking.h"

@interface DownLoadOperation :NSObject

@property(nonatomic ,strong) NSURL* url;

@property(nonatomic ,copy) NSString* (^cachePath)(void);

@property(nonatomic ,strong) AFHTTPRequestOperation* requestOperation;

@property(nonatomic ,copy) void(^progressBlock)(NSUInteger bytesRead,long long totalBytesRead,long longtotalBytesExpectedToRead);

-(void)downloadWithUrl:(id)url

cachePath:(NSString* (^) (void))cacheBlock

progressBlock:(void (^)(NSUInteger bytesRead,long long totalBytesRead,long longtotalBytesExpectedToRead))progressBlock

success:(void (^)(AFHTTPRequestOperation *operation,id responseObject))success

failure:(void (^)(AFHTTPRequestOperation *operation,NSError *error))failure;

@end

 

#import "DownLoadOperation.h"

@implementation DownLoadOperation

-(void)downloadWithUrl:(id)url

cachePath:(NSString* (^) (void))cacheBlock

progressBlock:(void (^)(NSUInteger bytesRead,long long totalBytesRead,long longtotalBytesExpectedToRead))progressBlock

success:(void (^)(AFHTTPRequestOperation *operation,id responseObject))success

failure:(void (^)(AFHTTPRequestOperation *operation,NSError *error))failure

{

self.cachePath = cacheBlock;

//获取缓存的长度

longlong cacheLength = [[selfclass] cacheFileWithPath:self.cachePath()];

NSLog(@"cacheLength = %llu",cacheLength);

//获取请求

NSMutableURLRequest* request = [[selfclass] requestWithUrl:urlRange:cacheLength];

self.requestOperation = [[AFHTTPRequestOperationalloc] initWithRequest:request];

[self.requestOperationsetOutputStream:[NSOutputStreamoutputStreamToFileAtPath:self.cachePath()append:NO]];

//处理流

[selfreadCacheToOutStreamWithPath:self.cachePath()];

[self.requestOperationaddObserver:selfforKeyPath:@"isPaused"options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOldcontext:nil];

//获取进度块

self.progressBlock = progressBlock;

//重组进度block

[self.requestOperationsetDownloadProgressBlock:[selfgetNewProgressBlockWithCacheLength:cacheLength]];

//获取成功回调块

void (^newSuccess)(AFHTTPRequestOperation *operation,id responseObject) = ^(AFHTTPRequestOperation *operation,idresponseObject){

NSLog(@"responseHead = %@",[operation.responseallHeaderFields]);

success(operation,responseObject);

};

[self.requestOperationsetCompletionBlockWithSuccess:newSuccess

failure:failure];

[self.requestOperationstart];

}

#pragma mark - 获取本地缓存的字节

+(longlong)cacheFileWithPath:(NSString*)path

{

NSFileHandle* fh = [NSFileHandlefileHandleForReadingAtPath:path];

NSData* contentData = [fhreadDataToEndOfFile];

return contentData ? contentData.length :0;

}

#pragma mark - 重组进度块

-(void(^)(NSUInteger bytesRead,long long totalBytesRead,long longtotalBytesExpectedToRead))getNewProgressBlockWithCacheLength:(longlong)cachLength

{

typeof(self)newSelf =self;

void(^newProgressBlock)(NSUInteger bytesRead,long long totalBytesRead,long long totalBytesExpectedToRead) = ^(NSUInteger bytesRead,long long totalBytesRead,long long totalBytesExpectedToRead)

{

NSData* data = [NSDatadataWithContentsOfFile:self.cachePath()];

[self.requestOperationsetValue:dataforKey:@"responseData"];

//        self.requestOperation.responseData = ;

newSelf.progressBlock(bytesRead,totalBytesRead + cachLength,totalBytesExpectedToRead + cachLength);

};

return newProgressBlock;

}

 

#pragma mark - 读取本地缓存入流

-(void)readCacheToOutStreamWithPath:(NSString*)path

{

NSFileHandle* fh = [NSFileHandlefileHandleForReadingAtPath:path];

NSData* currentData = [fhreadDataToEndOfFile];

if (currentData.length) {

//打开流,写入data,未打卡查看 streamCode = NSStreamStatusNotOpen

[self.requestOperation.outputStreamopen];

NSInteger       bytesWritten;

NSInteger       bytesWrittenSoFar;

NSInteger  dataLength = [currentDatalength];

constuint8_t * dataBytes  = [currentDatabytes];

bytesWrittenSoFar = 0;

do {

bytesWritten = [self.requestOperation.outputStreamwrite:&dataBytes[bytesWrittenSoFar]maxLength:dataLength - bytesWrittenSoFar];

assert(bytesWritten !=0);

if (bytesWritten == -1) {

break;

} else {

bytesWrittenSoFar += bytesWritten;

}

} while (bytesWrittenSoFar != dataLength);

}

}

#pragma mark - 获取请求

+(NSMutableURLRequest*)requestWithUrl:(id)url Range:(longlong)length

{

NSURL* requestUrl = [urlisKindOfClass:[NSURLclass]] ? url : [NSURLURLWithString:url];

NSMutableURLRequest* request = [NSMutableURLRequestrequestWithURL:requestUrl

cachePolicy:NSURLRequestReloadIgnoringCacheData

timeoutInterval:5*60];

if (length) {

[request setValue:[NSStringstringWithFormat:@"bytes=%lld-",length]forHTTPHeaderField:@"Range"];

}

NSLog(@"request.head = %@",request.allHTTPHeaderFields);

return request;

}

#pragma mark - 监听暂停

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void*)context

{

NSLog(@"keypath = %@ changeDic = %@",keyPath,change);

//暂停状态

if ([keyPathisEqualToString:@"isPaused"] && [[changeobjectForKey:@"new"]intValue] ==1) {

longlong cacheLength = [[selfclass] cacheFileWithPath:self.cachePath()];

//暂停读取data从文件中获取到NSNumber

cacheLength = [[self.requestOperation.outputStreampropertyForKey:NSStreamFileCurrentOffsetKey]unsignedLongLongValue];

NSLog(@"cacheLength = %lld",cacheLength);

[self.requestOperationsetValue:@"0"forKey:@"totalBytesRead"];

//重组进度block

[self.requestOperationsetDownloadProgressBlock:[selfgetNewProgressBlockWithCacheLength:cacheLength]];

}

@end

 

AFNetworking实现 断点续传的更多相关文章

  1. AFNetworking实现程序重新启动时的断点续传

    今天需要用AFNetworking实现断点续传的功能,但是在进行了一番研究之后,发现AFNetworking虽然支持下载文件的暂停和继续,但是程序重新启动后再次下载无法进行续传.网上有说可以通过AFD ...

  2. AFNetworking 3.0 断点续传 使用记录

    最近项目中用到了压缩包下载,使用AFNetworking 3.0 下载压缩包 支持断点续传 代码如下: #import "HDInternet_handler.h" #import ...

  3. AFNetworking 下载文件断点续传操作

    一:本示例代码包括: 文件下载,写入指定目录 下载进度,回调Progress; 断点续传,下载暂停,继续操作: 二:本项目 适用于 AFNetworking 1.x 版本 #pragma mark 断 ...

  4. 使用 AFNetworking做过断点续传吗?

    断点续传的主要思路: 检查服务器文件信息 检查本地文件 如果比服务器文件小, 断点续传, 利用 HTTP 请求头的 content-range实现断点续传(如果content-range不存在就取Co ...

  5. 【原】AFNetworking源码阅读(四)

    [原]AFNetworking源码阅读(四) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇还遗留了很多问题,包括AFURLSessionManagerTaskDe ...

  6. 【原】AFNetworking源码阅读(三)

    [原]AFNetworking源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇的话,主要是讲了如何通过构建一个request来生成一个data tas ...

  7. 总结iOS开发中的断点续传那些事儿

    前言 断点续传概述 断点续传就是从文件赏赐中断的地方重新开始下载或者上传数据,而不是从头文件开始.当下载大文件的时候,如果没有实现断点续传功能,那么每次出现异常或者用户主动的暂停,都会从头下载,这样很 ...

  8. AFNetworking到底做了什么?(二)

      接着上一篇的内容往下讲,如果没看过上一篇内容可以点这: AFNetworking到底做了什么? 之前我们讲到NSUrlSession代理这一块: 代理8: /* task完成之后的回调,成功和失败 ...

  9. AFNetworking、MKNetworkKit和ASIHTTPRequest对比

    之前一直在使用ASIHTTPRequest作为网络库,但是由于其停止更新,iOS7上可能出现更多的问题,于是决定更换网络库. 目前比较流行的网络库主要有AFNetworking和MKNetworkKi ...

随机推荐

  1. 创建一个自己的动态HTML-备

    -.获取元素 改变属性 通过id来获取HTML元素 通过标签名找到HTML元素 通过类名来找到HTML元素 举个

  2. 怪胎:Android开发ImageView图片无法显示

    今天碰到一个非常奇怪的问题: 在Android中ImageView无法显示加载的本地SDCard图片. 具体过程是:先调用本地照相机程序摄像,然后将拍摄的图片加载在ImageView中显示. publ ...

  3. SSH本地端口转发

    也是在公司常用的命令,还没有将EXPECT和SPAWN结合好,先用着: 带证书验证远程登陆的. (从公司内网服务器直接跳到外网服务器的内网端口) ssh -C -f -N -g -i private_ ...

  4. C 和 C++的 不同

    转自: http://studytipsandtricks.blogspot.com/2012/05/15-most-important-differences-between-c.html Basi ...

  5. CPU卡中T=0通讯协议的分析与实现

    IC卡的应用越来越广泛,从存储卡到逻辑加密卡,目前CPU卡已经逐渐在应用中占据主导地位.CPU卡根据通讯协议可分为两种:接触式和非接触式.接触式CPU卡主要采用两种通讯协议:T=0和T=1通讯协议.T ...

  6. 疯狂delphi - 朱建强 (一些小例子很实用,也是我所关心的几个问题)

    疯狂delphi - 朱建强 (一些小例子很实用,也是我所关心的几个问题) Android实例-获取安卓手机WIFI信息(XE8+小米2)http://www.cnblogs.com/FKdelphi ...

  7. puppet cert maintain

  8. swift 自定义导航栏颜色

    func setNavigationApperance(){ //自定义导航栏颜色 [self.navigationController?.navigationBar.barTintColor = U ...

  9. Android学习总结——强制下线功能(广播)

    最近一口气买了好几本书,其中Android的<第一行代码>觉得真心不错,学到这个内容,顺便做个总结,加深印象. 强制下线的基本思想就是在界面上弹出一个对话框,让用户必须点击确定按钮跳转到登 ...

  10. HTML浅识

    HTML相关======= ## 认识网页 *web标准(w3c三种标准):结构标准 -->html 表现标准 -->css 行为标准 -->js **浏览器和服务器:浏览器发送报文 ...