IOS数据操作:文件下载(内存优化&断点续传)

8 篇文章 0 订阅
   

    IOS开发中一般会用到数据下载操作,下载的内容分为小文件和大文件下载方式又分为异步跟同步。

    

    一 小文件

 

    上面无论是A还是B方式进行大的数据下载操作都非常不好,A跟B首先它都会在主线程内进行下载操作,等到数据下载完毕它才会继续让程序往下执行。而且也无法监视下载进度,影响用户体验,还有一个弊端就是下载的数据都会一个劲的往data这个变量里面塞而它又是存放在内存中的,如果你的URL路径资源是50MB那么你的程序占用的内存将随着这个data迅速猛增,内存资源将会非常危险也很致命,所以开发中绝对不会采取这种方式,它只能适合小的数据下载。

       

        二 :大文件

     实现过程:  创建四个关联对象

<span style="font-size:14px;color:#CC0000;">NSURLSessionConfiguration 配合 Session</span>
<span style="font-size:14px;color:#CC0000;">NSURLSession  任务类</span>
<span style="font-size:14px;color:#CC0000;">NSFileManager 文件管理类</span>
<span style="font-size:14px;color:#CC0000;">NSURLSessionDataTask 任务类型

</span>
<span style="font-size:14px;color:#CC0000;">NSURLSessionDataDelegate 实现代理的两个方法
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data</span>
<span style="font-size:14px;color:#CC0000;">- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error</span>

 

<span style="font-size:14px;color:#CC0000;"> #import "ViewController.h"
 #import "DACircularProgressView.h"
 @interface ViewController ()<NSURLSessionDataDelegate>
 @property (weak, nonatomic) IBOutlet UIImageView *pictureView;
 
 /**
 *  管理session
 */
@property (nonatomic,strong)NSURLSessionConfiguration* configuration;
/**
 *  任务
 */
@property (nonatomic,strong)NSURLSession* session;
/**
 *  图片数据
 */
@property (nonatomic,strong)NSMutableData* data;
/**
 *  图片URL资源
 */
@property (nonatomic,strong)NSMutableArray* allPicture;
/**
 *  文件管理
 */
@property (nonatomic,strong)NSFileManager* manager;
/**
 *  下标
 */
@property (nonatomic,assign)NSInteger index;
/**
 *  下载进度
 */
@property (weak, nonatomic)DACircularProgressView *downProgress;
@end

@implementation ViewController
- (NSFileManager *)manager
{
    if (!_manager)
    {
        _manager = [NSFileManager defaultManager];
    }
    return _manager;
}
- (NSMutableArray *)allPicture
{
    if (!_allPicture)
    {
        _allPicture = [NSMutableArray array];
    }
    return _allPicture;
}
/**
 *  懒加载
 */
- (NSURLSession*)session
{
    if (!_session)
    {
        _configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
        _session = [NSURLSession sessionWithConfiguration:_configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
        
    }
    return _session;
}
/**
 *  沙盒路径
 */
- (NSString*)returnTheFilePatch:(NSString*)url
{
    NSString* last = url.lastPathComponent;
    NSString* patch = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    
    return [patch stringByAppendingPathComponent:last];
}
#pragma makr 监听下载进度
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
    
    
    // 主线程刷新
    dispatch_async(dispatch_get_main_queue(), ^{
        // 获取url路径
        NSString* result = self.allPicture[self.index];
        // 拼接返回路径
        NSString* patch = [self returnTheFilePatch:result];
        // 创建文件句柄
        NSFileHandle* filehandle = [NSFileHandle fileHandleForWritingAtPath:patch];
        [filehandle seekToEndOfFile];
        // 继续写入数据
        [filehandle writeData:data];
        // 关闭句柄
        [filehandle closeFile];
        // 显示到控件
        self.pictureView.image = [UIImage imageWithContentsOfFile:patch];
        // 进度条
        self.downProgress.progress = dataTask.countOfBytesReceived*1.0/dataTask.countOfBytesExpectedToReceive;
    });
    
}
#pragma mark 下载完毕
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    
    // url下标
    ++self.index;
    // 下载
    [self downLoadImageUrl:self.allPicture[self.index]];
    // 清空原有图片数据
    self.data = nil;
    
}
/**
 *  大文件下载
 */
- (IBAction)bigFileDown:(id)sender {
    
    // 拼接URL图片路径
    for (int m=5; m<=70; m++)
    {
        NSString* patch =[NSString stringWithFormat:@"http://t1.niutuku.com/960/59/59-1427%02d.jpg",m];
        [self.allPicture addObject:patch];
    }
    // 执行下载
    [self downLoadImageUrl:self.allPicture[0]];
    
}
/**
 *  下载
 */
- (void)downLoadImageUrl:(NSString*)patch
{
    // 返回拼接路径
    NSString* filePatch = [self returnTheFilePatch:patch];
    // 创建空文件
    [self.manager createFileAtPath:filePatch contents:nil attributes:nil];
    // url资源
    NSURL* URL = [NSURL URLWithString:patch];
    // 创建任务
    NSURLSessionDataTask* dataTastk = [self.session dataTaskWithURL:URL];
    // 执行
    [dataTastk resume];
}
- (void)viewDidLoad {
    // 创建进度条View
    DACircularProgressView* dacircul = [[DACircularProgressView alloc] init];
    self.downProgress = dacircul;
    dacircul.trackTintColor = [UIColor blackColor];
    dacircul.frame = CGRectMake(130, 200, 60, 60);
    [self.view addSubview:dacircul];
    self.index = 0;
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}</span>

效果:


        三 :断点续传

实现过程: 

更改任务类型:

<span style="font-size:14px;color:#CC0000;"></span><pre name="code" class="objc"><span style="font-size:14px;color:#CC0000;">NSURLSessionDownloadTask</span>

 

添加协议

<span style="font-size:14px;color:#CC0000;">NSURLSessionDownloadDelegate
</span>
增加一个 NSdata变量用于记录下载进度
<span style="font-size:14px;color:#CC0000;">@property (nonatomic,strong)NSData* data;</span>
实现两个协议 (下载完毕)(正在下载)
<span style="font-size:14px;color:#CC0000;">- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
</span>
增加三个方法
<span style="font-size:14px;color:#CC0000;">start(开始) pause(暂停) 恢复(recover)</span>

代码:

<span style="font-size:14px;color:#FF0000;">@interface myView ()<NSURLSessionDownloadDelegate>
/**
 *  图片URL资源
 */
@property (nonatomic,strong)NSMutableArray* allPicture;
/**
 *  图片View
 */
@property (weak, nonatomic) IBOutlet UIImageView *pictureView;
/**
 * 下载任务
 */
@property (nonatomic,strong)NSURLSessionDownloadTask* task;
/**
 * 执行
 */
@property (nonatomic,strong)NSURLSession* session;
/**
 *  断点数据
 */
@property (nonatomic,strong)NSData* data;
/**
 *  进度
 */
@property (nonatomic,strong)HiProgressView* downPlan;
/**
 *  下载按钮
 */
@property (weak, nonatomic) IBOutlet UIButton *downBtn;
/**
 *  图片下标
 */
@property (nonatomic,assign)NSInteger index;
@end

@implementation myView
- (NSMutableArray *)allPicture
{
    if (!_allPicture)
    {
        _allPicture = [NSMutableArray array];
    }
    return _allPicture;
}

- (NSURLSession *)session
{
    if (!_session)
    {
        NSURLSessionConfiguration* configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
        
        _session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    }
    return _session;
}
/**
 *  开始
 */
- (void)start
{
    [self.downBtn setTitle:@"暂停" forState:UIControlStateNormal];
    // 取出url路径
    NSString* patch = self.allPicture[self.index];
    // 开始下载
    [self downLoadImageUrl:patch];
}
/**
 *  暂停
 */
- (void)pause
{
    [self.downBtn setTitle:@"开始" forState:UIControlStateNormal];
    //防止无法释放
    __weak typeof(self)View = self;
    [self.task cancelByProducingResumeData:^(NSData *resumeData) {
        // 保存数据
        View.data = resumeData;
        // 删除任务
        self.task = nil;
    }];
    
}
/**
 *  恢复
 */
- (void)recover
{
    [self.downBtn setTitle:@"暂停" forState:UIControlStateNormal];
    // 传入上次数据
    self.task = [self.session downloadTaskWithResumeData:self.data];
    // 继续执行
    [self.task resume];
    // 清空
    self.data = nil;
}
#pragma mark 下载
- (IBAction)downPicture:(id)sender
{
    
    if (self.task == nil)
    {
        if (self.data == nil)
        {
            [self start];
            
        }else
        {
            [self recover];
        }
        
    }else
    {
        [self pause];
    }
}

/**
 *  下载
 */
- (void)downLoadImageUrl:(NSString*)patch
{
    // 图片下标
    ++self.index;
    // url资源
    NSURL* URL = [NSURL URLWithString:patch];
    // 创建任务
    self.task = [self.session downloadTaskWithURL:URL];
    // 执行
    [self.task resume];
}

#pragma mark 下载完毕执行
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
    // 拿到沙盒文件夹路径
    NSString* caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject];
    // 路径拼接
    NSString* patch = [caches stringByAppendingPathComponent:location.lastPathComponent];
    // 移动文件夹
    NSFileManager* fileManage = [NSFileManager defaultManager];
    [fileManage moveItemAtPath:location.path toPath:patch error:nil];
    // 显示到数据
    dispatch_async(dispatch_get_main_queue(), ^{
        self.pictureView.image = [UIImage imageWithContentsOfFile:patch];
        // 继续下载
        NSString* urlPatch = self.allPicture[self.index];
        [self downLoadImageUrl:urlPatch];
    });

}
#pragma mark 监听进度
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
    self.downPlan.progress = totalBytesWritten*1.0 / totalBytesExpectedToWrite;
}

/**
 *  沙盒路径
 */
- (NSString*)returnTheFilePatch:(NSString*)url
{
    NSString* last = url.lastPathComponent;
    NSString* patch = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    
    return [patch stringByAppendingPathComponent:last];
}
- (void)viewDidLoad {
    self.index = 0;
    // 拼接URL图片路径
    for (int m=5; m<=70; m++)
    {
        NSString* patch =[NSString stringWithFormat:@"http://t1.niutuku.com/960/59/59-1427%02d.jpg",m];
        [self.allPicture addObject:patch];
    }
    // 下载进度
    CGRect rect = CGRectMake(0, 150, 320, 10);
    HiProgressView *progressView = [[HiProgressView alloc]initWithFrame:rect withProgress:0];//传入参数范围0~1
    [self.view addSubview:progressView];
    self.downPlan = progressView;
    [super viewDidLoad];
}</span>

效果图


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值