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. 一个关于poi导出的API

    先准备需要的参数 参数1:String title=“用户信息” 参数2:String[] headers String[] headers = { "用户名", "昵称 ...

  2. CSS3 Flexbox布局那些事

    相信研究过CSS3的同学对Flexbox布局一定不会陌生(作为一个未来主流的布局方式,至少有所耳闻).最近完成了两个项目:一个是移动端H5项目,一个是嵌入HTML页面的mac客户端项目.为了庆祝这两个 ...

  3. cf B. Dima and Text Messages

    http://codeforces.com/contest/358/problem/B 先按照题意说的构造一个字符串s,然后与对比的字符串T比较,看看在字符串T中顺序查找有没有字符串S的所有字符,有输 ...

  4. Codeforces 540D Bad Luck Island

    http://codeforces.com/problemset/problem/540/D 题目大意: 会出石头.剪刀.布的人分别有r,s,p个,他们相互碰到的概率相同,输的人死掉,问最终活下去的人 ...

  5. IComparer<T> 接口Linq比较接口

    IComparer<T>比较两个对象并返回一个值,指示一个对象是小于.等于还是大于另一个对象. 在Linq当中,很多扩展方法接受一个实现IComparer<T>接口的实例的对象 ...

  6. bzoj4033

    http://www.lydsy.com/JudgeOnline/problem.php?id=4033 树形DP. 我们发现,每条边都是一条桥,若我们知道这条边其中一侧有多少个黑点,我们就可以知道这 ...

  7. 深入super,看Python如何解决钻石继承难题

    1.   Python的继承以及调用父类成员 python子类调用父类成员有2种方法,分别是普通方法和super方法 假设Base是基类 class Base(object): def __init_ ...

  8. c语言条件表达式误区1

    #include <stdio.h> #include <stdlib.h> //综合1 和 2我们知道牢记条件表达式中常量写在左边的语法规则 以防因为疏忽造成难以查找的错误 ...

  9. spring简单入门示例

    1 控制反转IOC\依赖注入DI,因为翻译的不同,因此有两个名字.       控制反转意思就是说,当我们调用一个方法或者类时,不再有我们主动去创建这个类的对象,控制权交给别人(spring). 依赖 ...

  10. hdu 4586 Play the Dice(概率dp)

    Problem Description There is a dice with n sides, which are numbered from 1,2,...,n and have the equ ...