文件的断点续传(即下载),同时保存到指定目录

来源:互联网 发布:linux c file 头文件 编辑:程序博客网 时间:2024/06/05 11:07

https://github.com/potato512/SYDemo_SYDownloadTask

在网络处理中,特别是对文件进行下载操作时,可能会出现网络异常导致的下载中断,或是设备电池没有电时的中断,又或是人为的中断。为了避免从头开始进行下载,即从下载中断点继续开始下载,这时候我们就需要使用到断点续传技术。

在iOS中,我们可以使用NSURLSession,NSURLSessionDownloadTask进行继点续传的处理。

在实现过程中有两点需要注意:

1、断点续传过程中,中断时要记录中断时的信息,以便重新进行下载时可以从中断点开始下载;

2、断点续传结束后,需要将文件保存在指定目录中,以便于后续的操作;

具体实现代码如下:

1、封装断点续传下载类

// .h文件#import <Foundation/Foundation.h>@interface SYDownloadTask : NSObject/** *  下载区域 */@property (nonatomic, strong, readonly) NSData *resumeData;/** *  开始下载 * *  @param url      下载地址 *  @param complete 下载回调 */- (void)downloadStartWithURL:(NSString *)url complete:(void (^)(BOOL isFinish, NSString *filePath, long long downloadBytes, long long totalBytes))complete;/** *  继续下载 * *  @param data     下载区域 *  @param complete 下载回调 */- (void)downloadStartWithData:(NSData *)data complete:(void (^)(BOOL isFinish, NSString *filePath, long long downloadBytes, long long totalBytes))complete;/** *  停止,或暂停下载 */- (void)downloadStop;@end
// .m文件#import "SYDownloadTask.h"@interface SYDownloadTask () <NSURLSessionDownloadDelegate>@property (nonatomic, strong) NSData *downloadData;@property (nonatomic, copy) void (^DownloadComplete)(BOOL isFinish, NSString *filePath, long long downloadBytes, long long totalBytes);@property (nonatomic, assign) BOOL isFinish;@property (nonatomic, assign) long long downloadBytes;@property (nonatomic, assign) long long totalBytes;@property (nonatomic, strong) NSURLSessionDownloadTask *dataTask;@property (nonatomic, strong) NSURLSession *dataSession;@end@implementation SYDownloadTask#pragma mark - getter- (NSURLSession *)dataSession{    if (!_dataSession)    {        NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];        _dataSession = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];    }                            return _dataSession;}- (NSData *)resumeData{    return self.downloadData;}#pragma mark - 方法/** *  开始下载 * *  @param url      下载地址 *  @param complete 下载回调 */- (void)downloadStartWithURL:(NSString *)url complete:(void (^)(BOOL isFinish, NSString *filePath, long long downloadBytes, long long totalBytes))complete{    if (complete)    {        self.DownloadComplete = [complete copy];    }    NSURL *urlStr = [NSURL URLWithString:url];    self.dataTask = [self.dataSession downloadTaskWithURL:urlStr];    [self.dataTask resume];}/** *  继续下载 * *  @param data     下载区域 *  @param complete 下载回调 */- (void)downloadStartWithData:(NSData *)data complete:(void (^)(BOOL isFinish, NSString *filePath, long long downloadBytes, long long totalBytes))complete{    if (complete)    {        self.DownloadComplete = [complete copy];    }        self.dataTask = [self.dataSession downloadTaskWithResumeData:data];    [self.dataTask resume];}/** *  停止,或暂停下载 */- (void)downloadStop{    __weak typeof(self) weakSelf = self;    [self.dataTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {        weakSelf.downloadData = resumeData;    }];}#pragma mark - NSURLSessionDownloadDelegate- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{    self.isFinish = YES;        // 将文件默认下载到我们的tmp文件夹中,我们还需要将该文件移动到我们的cache当中    NSString *destPath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;    NSString *fileName = [destPath stringByAppendingPathComponent:downloadTask.response.suggestedFilename];    NSFileManager *fileManager = [NSFileManager defaultManager];    [fileManager moveItemAtURL:location toURL:[NSURL fileURLWithPath:fileName] error:nil];        // 下载完成    if (self.DownloadComplete)    {        self.DownloadComplete(self.isFinish, fileName, self.downloadBytes, self.totalBytes);    }}- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{    self.downloadBytes = totalBytesWritten;    self.totalBytes = totalBytesExpectedToWrite;        // 正在下载    if (self.DownloadComplete)    {        self.DownloadComplete(self.isFinish, nil, self.downloadBytes, self.totalBytes);    }}@end

2、使用断点续传下载类

// 导入头文件#import "SYDownloadTask.h"
// 定义成属性@property (nonatomic, strong) SYDownloadTask *downloadTask;
// 使用,即实例化,或开始,暂停下载,继续下载- (void)buttonClick:(UIButton *)button{    if (button.selected)    {        if (self.downloadTask)        {            [self.downloadTask downloadStop];        }    }    else    {        __weak typeof(self) weakSelf = self;        if (self.downloadTask)        {            [self.downloadTask downloadStartWithData:self.downloadTask.resumeData complete:^(BOOL isFinish, NSString *filePath, long long downloadBytes, long long totalBytes) {                                NSLog(@"1 下载状态:%@", (isFinish ? @"下载完成" : @"正在下载"));                NSLog(@"1 下载文件路径:%@", filePath);                NSLog(@"1 已下载:%f%%(downloadBytes = %f, totalBytes = %f)", (float)(downloadBytes)/(float)(totalBytes), (float)downloadBytes, (float)totalBytes);                                weakSelf.progressView.progress = (float)(downloadBytes)/(float)(totalBytes);                if (isFinish)                {                    button.selected = NO;                }            }];        }        else        {            NSString *string = @"http://sohu.vodnew.lxdns.com/193/142/tas6Zt4gReWdeh2eiBm7yD.mp4";//            NSString *string = @"http://www.68mtv.com/index/down/id/61109";//            NSString *string = @"http://imgsrc.baidu.com/baike/pic/item/203fb80e7bec54e7c5cda6b3bd389b504fc26a7e.jpg";            self.downloadTask = [[SYDownloadTask alloc] init];            [self.downloadTask downloadStartWithURL:string complete:^(BOOL isFinish, NSString *filePath, long long downloadBytes, long long totalBytes) {                NSLog(@"2 下载状态:%@", (isFinish ? @"下载完成" : @"正在下载"));                NSLog(@"2 下载文件路径:%@", filePath);                NSLog(@"2 已下载:%f%%(downloadBytes = %f, totalBytes = %f)", (float)(downloadBytes)/(float)(totalBytes), (float)downloadBytes, (float)totalBytes);                                weakSelf.progressView.progress = (float)(downloadBytes)/(float)(totalBytes);                if (isFinish)                {                    button.selected = NO;                }            }];        }    }        button.selected = !button.selected;}




0 0
原创粉丝点击