通过AFN3.0实现断点下载

AFN3.0的网络请求都是通过创建一个NSURLSessionTask是完成的,而下载则是实现NSURLSessionTask的子类NSURLSessionDownloadTask。

普通下载只要调用

- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request

                                             progress:(void (^)(NSProgress *downloadProgress)) downloadProgressBlock

                                          destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination

                                    completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler方法就能完成了。但是断点下载与普通下载不一样,断点下载的请求投信息中包含了一个“Range byte xxxx-”信息,其中xxxx是上次下载结束的地方,服务器返回的response也不一样,普通下载返回的是200,头信息中含有“content-length xxxxx”,ios自带框架中会自动识别content-length,并把它当作下载文件的总长度(其实content-length并不是真正意义上的文件总大小)。把它传递给 NSURLSESSION 的countOfBytesExpectedToReceive。断点下载返回的是206,头信息中不含有“content-length”,而是“content-range byte 1111-22222/22222”,其中1111是上次下载结束的地方+1,22222是文件总大小,由于返回体中没有content-length,所以NSURLSEEION无法获取当前下载总大小,所以AFN无法调用 self.downloadProgressBlock(object)方法,所以不能进入断点下载过程。

解决方法:

AFN3.0中设置了好几个回调方法,其中有一个回调方法是setDownloadTaskDidWriteDataBlock。AFN中的说明是这样的

/**

 Sets a block to be executed periodically to track download progress, as handled by the `NSURLSessionDownloadDelegate` method `URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesWritten:totalBytesExpectedToWrite:`.

 

 @param block A block object to be called when an undetermined number of bytes have been downloaded from the server. This block has no return value and takes five arguments: the session, the download task, the number of bytes read since the last time the download progress block was called, the total bytes read, and the total bytes expected to be read during the request, as initially determined by the expected content size of the `NSHTTPURLResponse` object. This block may be called multiple times, and will execute on the session manager operation queue.

 */

- (void)setDownloadTaskDidWriteDataBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite))block;

就是阶段性读取服务器的数据其中bytesWritten是当前阶段的下载量,并且该方法是在下载过程不断重复调用的,并且最关键的是该方法中有我们需要的downloadTask,该任务中的response含有我们需要的content-range。所以我们通过自己解析content-range字段来获取总大小。具体实现如下:

    [self setDownloadTaskDidWriteDataBlock:^(NSURLSession * _Nonnull session, NSURLSessionDownloadTask * _Nonnull downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite) {

          NSHTTPURLResponse *httpresponse = (NSHTTPURLResponse *)downloadTask.response;

        if(httpresponse.statusCode == 206)

        {

            NSString *contentRange = [httpresponse.allHeaderFields valueForKey:@"Content-Range"];

            if ([contentRange hasPrefix:@"bytes"]) {

                NSArray *bytes = [contentRange componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@" -/"]];

                if ([bytes count] == 4) {

                    int64_t totalSize = (int64_t)[[bytes objectAtIndex:2] longLongValue]; // if this is *, it's converted to 0

                    progress(1.0*totalBytesWritten/totalSize,totalBytesWritten,totalSize);

                }

            }

        }

    }];

转载于:https://my.oschina.net/microSpeak/blog/853559

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值