zoukankan      html  css  js  c++  java
  • 【iOS】文件下载小记

    下载文件到NSURLConnectionNSURLSession两种,一种有恨悠久的历史了。

    使用相对麻烦,后者是新出来的,添加了一些额外的功能。

    一、NSURLConnection实现下载

    TIPS:

    1、NSURLConnection下载时,得到的NSData写入文件,data并没有占用多大内存(即使文件非常大)
    2、一点点在传做的是磁盘缓存.而不是内存缓存机制。
    3、了解在NSURLConnection上加代理。

    [consetDelegateQueue:[[NSOperationQueuealloc]init]]

    4、NSURLResponse记录的了url, mineType, exceptedContentLength, suggestedFileName等属性. 下载时用得着.  

    下面程序实现追踪下载百分比的下载(URLConnection自带的方法):

    #import "XNDownload.h"
    
    typedef void(^ProgressBlock)(float percent);
    
    @interface XNDownload() <NSURLConnectionDataDelegate>
    
    @property (nonatomic, strong) NSMutableData *dataM;
    
    // 保存在沙盒中的文件路径
    @property (nonatomic, strong) NSString *cachePath;
    // 文件总长度
    @property (nonatomic, assign) long long fileLength;
    // 当前下载的文件长度
    @property (nonatomic, assign) long long currentLength;
    
    // 回调块代码
    @property (nonatomic, copy) ProgressBlock progress;
    
    @end
    
    @implementation XNDownload
    
    - (NSMutableData *)dataM
    {
        if (!_dataM) {
            _dataM = [NSMutableData data];
        }
        return _dataM;
    }
    
    - (void)downloadWithURL:(NSURL *)url progress:(void (^)(float))progress
    {
        // 0. 记录块代码
        self.progress = progress;
        
        // 1. request GET
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        
        // 2. connection
        NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
        
        // 让connection支持多线程。指定代理的工作队列就可以
        // NSURLConnection在执行时,执行循环不负责监听代理的详细执行
        [connection setDelegateQueue:[[NSOperationQueue alloc] init]];
        
        // 3. 启动连接
        [connection start];
    }
    
    #pragma mark - 代理方法
    // 1. 接收到server的响应。server执行完请求,向client回传数据
    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
    {
        NSLog(@"%@ %lld", response.suggestedFilename, response.expectedContentLength);
        // 1. 保存的缓存路径
        NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
        self.cachePath = [cachePath stringByAppendingPathComponent:response.suggestedFilename];
        // 2. 文件总长度
        self.fileLength = response.expectedContentLength;
        // 3. 当前下载的文件长度
        self.currentLength = 0;
        
        // 清空数据
        [self.dataM setData:nil];
    }
    
    // 2. 接收数据。从server接收到数据
    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    {
        // 拼接数据
        [self.dataM appendData:data];
        
        // 依据data的长度添加当前下载的文件长度
        self.currentLength += data.length;
        
        float progress = (float)self.currentLength / self.fileLength;
        
        // 推断是否定义了块代码
        if (self.progress) {
            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                // 强制执行循环执行一次更新
                [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate date]];
                
                self.progress(progress);
            }];
        }
    }
    
    // 3. 完毕接收
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection
    {
        NSLog(@"%s %@", __func__, [NSThread currentThread]);
        // 将dataM写入沙盒的缓存文件夹
        // 写入数据,NSURLConnection底层实现是用磁盘做的缓存
        [self.dataM writeToFile:self.cachePath atomically:YES];
    }
    
    // 4. 出现错误
    - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
    {
        NSLog(@"%@", error.localizedDescription);
    }
    
    @end

    二、NSURLSession实现下载

    NSURLSession能实现断点续传,暂停下载等功能。

    1、session提供的是开了多个线程的异步下载.
    2、下载的暂停续传(session代理中的方法)
    *弄一个NSData变量来保存下载东西.暂停时将下载任务task清空.
    *续传:将暂停时的data交给session继续下载,并将先前的data清空.
    3、task一定要resume才開始运行.

    #import "XNViewController.h"
    
    @interface XNViewController () <NSURLSessionDownloadDelegate>
    
    // 下载网络回话
    @property (nonatomic, strong) NSURLSession *session;
    // 下载任务
    @property (nonatomic, strong) NSURLSessionDownloadTask *downloadTask;
    // 续传的二进制数据
    @property (nonatomic, strong) NSData *resumeData;
    @end
    
    @implementation XNViewController
    
    - (NSURLSession *)session
    {
        if (!_session) {
            NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
            _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
        }
        return _session;
    }
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
        [self downloadFile];
    }
    
    // 暂停下载任务
    - (IBAction)pause
    {
        // 假设下载任务不存在,直接返回
        if (self.downloadTask == nil) return;
        
        // 暂停任务(块代码中的resumeData就是当前正在下载的二进制数据)
        // 停止下载任务时,须要保存数据
        [self.downloadTask cancelByProducingResumeData:^(NSData *resumeData) {
            self.resumeData = resumeData;
            
            // 清空而且释放当前的下载任务
            self.downloadTask = nil;
        }];
    }
    
    - (IBAction)resume
    {
        // 要续传的数据是否存在?
        if (self.resumeData == nil) return;
        
        // 建立续传的下载任务
        self.downloadTask = [self.session downloadTaskWithResumeData:self.resumeData];
        [self.downloadTask resume];
        
        // 将此前记录的续传数据清空
        self.resumeData = nil;
    }
    
    // 假设在开发中使用到缓存文件夹,一定要提供一个功能,“清除缓存”。
    /** 下载文件 */
    - (void)downloadFile
    {
        NSString *urlStr = @"http://localhost/苍老师全集.rmvb";
        urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        
        NSURL *url = [NSURL URLWithString:urlStr];
    
        // (1) 代理 & 直接启动任
        // 2. 启动下载任务
        self.downloadTask = [self.session downloadTaskWithURL:url];
        
        [self.downloadTask resume];
    }
    
    #pragma mark - 下载代理方法
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
    {
        NSLog(@"完毕 %@ %@", location, [NSThread currentThread]);
    }
    
    /**
     bytesWritten               : 本次下载的字节数
     totalBytesWritten          : 已经下载的字节数
     totalBytesExpectedToWrite  : 下载总大小
     */
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
    {
        float progress = (float)totalBytesWritten / totalBytesExpectedToWrite;
        
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            //主线程中更新进度UI操作。。。。
        }];
    }
    
    /** 续传的代理方法 */
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
    {
        NSLog(@"offset : %lld", fileOffset);
    }
    
    @end

    出处:http://blog.csdn.net/xn4545945



    版权声明:本文博主原创文章。博客,未经同意不得转载。

  • 相关阅读:
    git的使用
    免安装版mySQL的安装及配置
    Eclipse中安装freemarker插件
    freemarker配置
    Matlab机器人工具箱安装教程
    书籍推荐
    电影推荐
    自走棋地精猎玩法
    wineqq中接收文件的查看与移动
    windows和linux键值表
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4945816.html
Copyright © 2011-2022 走看看