zoukankan      html  css  js  c++  java
  • 利用NSURLSession完成的断点续传功能

    首先是业务中的.h文件

    #import <UIKit/UIKit.h>
    #import "DenglSingleton.h"
    
    @protocol DownLoadVCdelegate <NSObject>
    
    -(void)DownloadCompletedWithIndex:(NSInteger)index;
    
    @end
    
    @interface DownLoadVC : UIViewController
    DenglSingletonH(DownLoadVC)
    @property (nonatomic,copy) NSDictionary *dic;
    
    @property (nonatomic,weak) id<DownLoadVCdelegate> delegate;
    
    @end
    #import "DownLoadVC.h"
    #import "UIView+denglFrame.h"
    #import "DBBackgroundBtn.h"
    #import "SVProgressHUD.h"
    
    #define dAllMusicPlistFilePath [[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject]stringByAppendingPathComponent:@"text"] stringByAppendingPathComponent:@"allmusic.plist"]
    #define filePath [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:self.fileName]
    
    @interface DownLoadVC ()<NSURLSessionDataDelegate>
    {
        NSString *_downloadTag;
    }
    
    @property (strong, nonatomic)  UIImageView *iconImageView;
    @property (strong, nonatomic)  UIImageView *bottomImageView;
    @property (strong, nonatomic)  UITextView *AppDescritionTextView;
    @property (strong, nonatomic)  UILabel *AppNameLabel;
    @property (strong, nonatomic) DBBackgroundBtn *downLoadBtn;
    @property (nonatomic,strong) UIButton *backBtn;
    @property (nonatomic,strong) UIImageView *backBtnImgView;
    @property (nonatomic,copy) NSString *currentName;
    
    /** 下载任务 */
    @property (nonatomic, strong) NSURLSessionDataTask *task;
    /** session */
    @property (nonatomic, strong) NSURLSession *session;
    /** 写文件的流对象 */
    @property (nonatomic, strong) NSOutputStream *stream;
    /** 文件的总长度 */
    @property (nonatomic, assign) NSInteger totalLength;
    /** 文件百分比 */
    @property (nonatomic, assign) float p;
    /** 文件名字 */
    @property (nonatomic, copy) NSString *fileName;
    /** 文件url */
    @property (nonatomic, strong) NSURL *url;
    /** 下载数据保存字典 */
    @property (nonatomic, strong) NSMutableDictionary *downloadingListDic;
    @end
    
    @implementation DownLoadVC
    DenglSingletonM(DownLoadVC)
    
    - (NSURLSession *)session
    {
        if (!_session) {
            _session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc]init]];
        }
        return _session;
    }
    
    - (NSOutputStream *)stream
    {
        if (!_stream) {
            _stream = [NSOutputStream outputStreamToFileAtPath:filePath append:YES];
        }
        return _stream;
    }
    
    -(void)startDownloadMusic{
        // 创建请求
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:self.url];
        // 设置请求头
        // Range : bytes=xxx-xxx
        NSInteger downloadLength = [[[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil][NSFileSize] integerValue];
        NSString *range = [NSString stringWithFormat:@"bytes=%zd-", downloadLength];
        [request setValue:range forHTTPHeaderField:@"Range"];
        
        // 创建一个Data任务
        self.task = [self.session dataTaskWithRequest:request];
        //    NSLog(@"test");
    }
    
    -(void)setDic:(NSDictionary *)dic{
        _dic = dic;
        
        self.fileName = [self.dic objectForKey:@"filename"];
        self.url = [NSURL URLWithString:[self.dic objectForKey:@"url"]];
        if (self.currentName == nil) {
            //初始化UI
            [self setUI];
            self.currentName = self.fileName;
            //取出上一次保存的下载进度
            self.downloadingListDic = [NSMutableDictionary dictionaryWithDictionary:[[NSUserDefaults standardUserDefaults]objectForKey:@"downloadingListDic"]];
            if (self.downloadingListDic == nil) {
                self.downloadingListDic = [NSMutableDictionary dictionary];
                [[NSUserDefaults standardUserDefaults] setObject:self.downloadingListDic forKey:@"downloadingListDic"];
                [[NSUserDefaults standardUserDefaults]synchronize];
            }
            self.p = [[self.downloadingListDic objectForKey:self.fileName] floatValue];
            self.downLoadBtn.progress = self.p;
            //
            if (self.p != 0) {
                [self.downLoadBtn setBackgroundImage:[UIImage imageNamed:@"download_pause"] forState:UIControlStateNormal];
            }
            
            
        }else{
            if (![self.currentName isEqualToString:self.fileName]) {
                //取消任务
                self.currentName = self.fileName;
                [self.session invalidateAndCancel];
                self.session = nil;
                //取出上一次保存的下载进度
                self.downloadingListDic = [NSMutableDictionary dictionaryWithDictionary:[[NSUserDefaults standardUserDefaults]objectForKey:@"downloadingListDic"]];
                if (self.downloadingListDic == nil) {
                    self.downloadingListDic = [NSMutableDictionary dictionary];
                    [[NSUserDefaults standardUserDefaults] setObject:self.downloadingListDic forKey:@"downloadingListDic"];
                    [[NSUserDefaults standardUserDefaults]synchronize];
                }
                self.p = [[self.downloadingListDic objectForKey:self.fileName] floatValue];
                self.downLoadBtn.progress = self.p;
                //
                if (self.p != 0) {
                    [self.downLoadBtn setBackgroundImage:[UIImage imageNamed:@"download_pause"] forState:UIControlStateNormal];
                }
                self.downLoadBtn.tag = 1;
            }
        }
        [self setDataWithDic:dic];
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    }
    
    -(void)viewWillDisappear:(BOOL)animated{
        [super viewWillDisappear:animated];
        
        [self.downloadingListDic setObject:[NSString stringWithFormat:@"%f",self.p] forKey:self.fileName];
        
        [[NSUserDefaults standardUserDefaults] setObject:self.downloadingListDic forKey:@"downloadingListDic"];
        [[NSUserDefaults standardUserDefaults]synchronize];
    }
    
    -(void)setUI{
        [[NSUserDefaults standardUserDefaults]setObject:@"no" forKey:@"begin"];
        self.view.backgroundColor = [UIColor whiteColor];
    
        //返回按钮
        self.backBtn = [[UIButton alloc]init];
        [self.backBtn addTarget:self action:@selector(clickBackBtn) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:self.backBtn];
        //
        self.AppNameLabel = [[UILabel alloc]init];
        self.AppNameLabel.textAlignment = NSTextAlignmentCenter;
        [self.view addSubview:self.AppNameLabel];
        //
        self.AppDescritionTextView = [[UITextView alloc]init];
        self.AppDescritionTextView.textColor = [UIColor grayColor];
        self.AppDescritionTextView.editable = NO;
        self.AppDescritionTextView.selectable = NO;
        [self.view addSubview:self.AppDescritionTextView];
        //
        self.bottomImageView = [[UIImageView alloc]init];
        [self.view addSubview:self.bottomImageView];
        //
        self.iconImageView = [[UIImageView alloc]init];
        [self.view addSubview:self.iconImageView];
        
        //
        self.downLoadBtn = [[DBBackgroundBtn alloc]init];
        [self.downLoadBtn setBackgroundImage:[UIImage imageNamed:@"download"] forState:UIControlStateNormal];
        self.downLoadBtn.tag = 1;
        self.downLoadBtn.progress = 0;
        [self.downLoadBtn addTarget:self action:@selector(clickdownLoadBtn:) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:self.downLoadBtn];
    
        //
        self.backBtnImgView = [[UIImageView alloc]init];
        self.backBtnImgView.image = [UIImage imageNamed:@"back_ipad.png"];
        [self.view addSubview:self.backBtnImgView];
    
    }
    
    -(void)viewDidLayoutSubviews{
        [super viewDidLayoutSubviews];
        [self setUIFrame];
    }
    
    -(void)setUIFrame{
        //下载按钮
        self.downLoadBtn.width = 100 / 1136.0 * self.view.height;
        self.downLoadBtn.height = self.downLoadBtn.width;
        self.downLoadBtn.x = (self.view.width - self.downLoadBtn.width)/2;
        self.downLoadBtn.y = 970 / 1136.0 * self.view.height;
    
        //图标
        self.iconImageView.width = 400 / 1136.0 * self.view.height;
        self.iconImageView.height = self.iconImageView.width;
        self.iconImageView.x = (self.view.width - self.iconImageView.width)/2;
        self.iconImageView.y = 128 / 1136.0 * self.view.height;
        
        //底部图
        self.bottomImageView.width = self.view.width;
        self.bottomImageView.height = 240 / 1136.0 * self.view.height;
        self.bottomImageView.x = 0;
        self.bottomImageView.y = 900 / 1136.0 * self.view.height;
    
        //AppNameLabel app名称
        self.AppNameLabel.width = self.view.width;
        self.AppNameLabel.height = 36 / 1136.0 * self.view.height;
        self.AppNameLabel.x = 0;
        self.AppNameLabel.y = 585 / 1136.0 * self.view.height;
        self.AppNameLabel.font = [UIFont systemFontOfSize:35 / 1136.0 * self.view.height];
        
        //AppDescritionTextView
        self.AppDescritionTextView.x = 35 / 1136.0 * self.view.height;
        self.AppDescritionTextView.width = self.view.width - self.AppDescritionTextView.x * 2;
        self.AppDescritionTextView.height = 250 / 1136.0 * self.view.height;
        self.AppDescritionTextView.y = 640 / 1136.0 * self.view.height;
        [self.AppDescritionTextView scrollRangeToVisible:NSMakeRange(0, 1)];
        //
        self.AppDescritionTextView.font = [UIFont systemFontOfSize:32 / 1136.0 * self.view.height];
        
        //返回按钮
        self.backBtn.width = 50;
        self.backBtn.height = 50;
        self.backBtn.x = 0;
        self.backBtn.y = 0;
        
        // 15 8 12 25
        self.backBtnImgView.width = 12 / 568.0 * self.view.height;
        self.backBtnImgView.height = 25 / 568.0 * self.view.height;
        self.backBtnImgView.x = 15/ 568.0 * self.view.height;
        self.backBtnImgView.y = 8/ 568.0 * self.view.height;
    }
    
    -(void)setDataWithDic:(NSDictionary*)dic{
        //
        NSString *iconImage = [dic objectForKey:@"image"];
        self.iconImageView.image = [UIImage imageNamed:iconImage];
        
        //
        NSString *bottomImage = [dic objectForKey:@"color"];
        self.bottomImageView.image = [UIImage imageNamed:bottomImage];
        
        //
        NSArray *AppNameArr = [dic objectForKey:@"name"];
        NSInteger index = [[NSUserDefaults standardUserDefaults] integerForKey:@"yuyan"];
        self.AppNameLabel.text = [AppNameArr objectAtIndex:index];
        
        //
        NSArray *AppDescritionArr = [dic objectForKey:@"info"];
        self.AppDescritionTextView.text = [AppDescritionArr objectAtIndex:index];
    }
    
    - (IBAction)clickdownLoadBtn:(id)sender {
        UIButton *btn = sender;
        if (btn.tag == 1) {//下载
            [self.downLoadBtn setBackgroundImage:[UIImage imageNamed:@"download"] forState:UIControlStateNormal];
            [self startDownloadMusic];
            [self.task resume];
            _downloadTag = @"resume";
        }else if (btn.tag == -1){//停止
            [self.downLoadBtn setBackgroundImage:[UIImage imageNamed:@"download_pause"] forState:UIControlStateNormal];
            if (self.session) {
                [self.session invalidateAndCancel];
                self.session =nil;
            }
            _downloadTag = @"stop";
        }
        btn.tag *= -1;
    }
    
    -(void)dealloc{
    }
    
    - (void)clickBackBtn {
        [self.navigationController popViewControllerAnimated:YES];
    }
    
    #pragma mark - NSURLSessionDataDelegate
    /**
     * 1.接收到响应
     */
    - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSHTTPURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
    {
        // 获得服务器这次请求 返回数据的总长度
        NSInteger downloadLength = [[[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil][NSFileSize] integerValue];
        self.totalLength = [response.allHeaderFields[@"Content-Length"] integerValue] + downloadLength;
        
        // 打开流
        [self.stream open];
        // 接收这个请求,允许接收服务器的数据
        completionHandler(NSURLSessionResponseAllow);
    }
    
    /**
     * 2.接收到服务器返回的数据
     */
    - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
    {
        [self.stream write:data.bytes maxLength:data.length];
        // 下载进度
        NSInteger downloadLength = [[[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil][NSFileSize] integerValue];
        self.p = 1.0 * downloadLength / self.totalLength;
        NSLog(@"%f",self.p);
        dispatch_async(dispatch_get_main_queue(), ^{
            self.downLoadBtn.progress = self.p;
        });
    }
    
    /**
     * 3.请求完毕(成功失败)
     */
    - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
    {
        // 关闭流
        [self.stream close];
        self.stream = nil;
        if (!error) {//没有错误信息
            if (task.state == NSURLSessionTaskStateCompleted) {
                NSLog(@"NSURLSessionTaskStateCompleted");
                 NSInteger index = [[self.dic objectForKey:@"index"] integerValue];
                //下载完成后,将曲目的下载状态做一次更新,将新的数组更新到plist文件中。
                NSMutableArray *arr = [NSMutableArray arrayWithContentsOfFile:dAllMusicPlistFilePath];
                NSMutableDictionary *dic = [arr objectAtIndex:index];
                [dic setObject:@"1" forKey:@"isDownLoad"];
                if ([arr writeToFile:dAllMusicPlistFilePath atomically:YES]) {
                    NSLog(@"writeToFileSuccess");
                }
                dispatch_async(dispatch_get_main_queue(), ^{
                    if (self.delegate && [self.delegate respondsToSelector:@selector(DownloadCompletedWithIndex:)]) {
                        [self.delegate DownloadCompletedWithIndex:index];
                    }
                    [self.navigationController popViewControllerAnimated:NO];
                });
            }
        }else{//有错误信息
            if (error.code == 18446744073709550617) {
                NSLog(@"用户取消");
            }else{
                [SVProgressHUD setMinimumDismissTimeInterval:3.5];
                [SVProgressHUD setDefaultStyle:SVProgressHUDStyleDark];
                NSString *str = NSLocalizedString(@"loadFaild", nil);
                [SVProgressHUD showErrorWithStatus:str];
            }
        }
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
  • 相关阅读:
    Oracle Golden Gate 系列十四 监控 GG 状态 说明
    Oracle Golden Gate 系列十六 配置 GG 安全 说明 与 示例
    带宽计算方法 及 大B与小b 说明
    带宽计算方法 及 大B与小b 说明
    Oracle LOB 详解
    Oracle bootstrap$ 详解
    Oracle 10g 中 X$KCVFH 说明
    RMAN 备份报错 RMAN06207 RMAN06208 解决方法
    Oracle Golden Gate 系列十三 配置GG进程检查点(checkpoint) 说明
    Oracle Lifetime Support(支持生命周期) 说明
  • 原文地址:https://www.cnblogs.com/iOSDeng/p/5395216.html
Copyright © 2011-2022 走看看