博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
AFNetworking实现 断点续传
阅读量:5325 次
发布时间:2019-06-14

本文共 7296 字,大约阅读时间需要 24 分钟。

 

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----------------------
 

#define Vedio @""

 

#define Picture @""

- (IBAction)download:(id)sender

{

//

//    

    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

 

转载于:https://www.cnblogs.com/iOS-mt/p/4320371.html

你可能感兴趣的文章
求1+2+…+n
查看>>
开发者必备的6款源码搜索引擎
查看>>
一个值只有0和1的字段,到底要不要建索引?
查看>>
JavaScript的Math对象
查看>>
form 禁止跳转
查看>>
第七周学习总结
查看>>
20145122《JAVA开发环境的熟悉》实验报告
查看>>
186. Reverse Words in a String II
查看>>
JAVA-初步认识-第五章-数组-常见操作-进制转换整合
查看>>
如何在.net4.0中使用.net4.5的async/await
查看>>
Spring自定义标签实现及踩过的坑(亲测)
查看>>
一些字符串的题
查看>>
第2章:标准输入与输出
查看>>
个人项目——买书
查看>>
POJ 2309 BST
查看>>
Codefroces 415B Mashmokh and Tokens
查看>>
HDU 3440 House Man
查看>>
Mysql 用户管理
查看>>
实验五
查看>>
焊接贴片
查看>>