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. FeatureClass Copy

    http://edndoc.esri.com/arcobjects/9.2/NET/c45379b5-fbf2-405c-9a36-ea6690f295b2.htm Method What is tr ...

  2. FLASH驱动之-块设备驱动系统构架

    一.  块设备是只能以块为单位进行访问的设备,块的大小一般是512个字节的整数倍,常见的块设备包括硬件,SD卡,光盘,flash等.驱动程序是块的整数倍从设备读写得到数据.块设备的最小访单位为块,不同 ...

  3. NGINX和PHP之间的环境变量传递

    昨天遇到的,想将IP访问转换成域名访问.则NGINX需要将相关的变量转换后传递给PHP. 网上有一系统的方法: 前面讲过该不该把信息写在服务器配置文件里?.通过php扩展hidef来define常量, ...

  4. Qt调用VC++生成的动态链接库

    Qt如何调用VC++生成的动态链接库?假设当前有VC++编译器生成的动态库文件testdll.h,testdll.lib和testdll.dll. testdll.h文件源码如下: #ifdef TE ...

  5. 常用的Windows批处理

      切换执行路径 如果不换盘的话:cd xxx换盘:cd /d xxx   获取当前日期 编写Windows批处理时经常会需要使用到日期和时间作为文件名,所以是非常重要的. 如何获取日期呢?格式:  ...

  6. ASP.NET WEB API 如何使用基于Post的方式传递多个值(二)

    前面我曾经写过一篇文章,是基于HttpContext的请求上下文中读取表单参数,其实还可以将其单独拆分出来. 基于Filter的方式 获取表单值:(核心代码)   public void OnActi ...

  7. 解决比较Oracle中CLOB字段问题

    解决比较Oracle中CLOB字段问题   Oracle中CLOB和BLOB字段虽说在开发中满足了存放超大内容的要求,但是在一些简单使用中确频频带来麻烦.CLOB中存放的是指针,并不能直接取到实际值. ...

  8. eclipse,tomcat部署web项目,以及本地文件访问

    1.直接把项目复制到Tomcat安装目录的webapps目录中,这是最简单的一种Tomcat项目部署的方法,也是初学者最常用的方法. 2.在tomcat安装目录中有一个conf文件夹,打开此文件夹,其 ...

  9. poj2752 Seek the Name, Seek the Fame

    Description The little cat is so famous, that many couples tramp over hill and dale to Byteland, and ...

  10. cf413E Maze 2D

    E. Maze 2D time limit per test 2 seconds memory limit per test 256 megabytes input standard input ou ...