iOS开发网络篇 一一 NSURLSessionDownloadTask实现文件下载

NSURLSessionDownloadTask文件下载 和 NSURLConnection 下载的区别:

使用NSURLSessionDownloadTask任务来下载文件,不需要保存到沙盒中,downloadTaskWithRequest:comp 方法会自动将请求的数据,保存到沙盒中.

所以不需要手动将下载的数据写入到沙盒中.


知识点: 

1. 使用block块的方式来下载数据无法监听数据的下载进度. 使用代理的方法可以监听数据的下载进度


2. NSURLSessionDownloadTask任务 会自动做沙盒缓存,将数据保存到 tmp 中.


3. location 属性: 数据保存到临时数据沙盒tmp中的路径


4. 需要location 剪切到 指定文件下载的路径
[[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:fullPath] error:nil];
5. 获得下载文件的 名称及后缀的两种方式:
NSLog(@"%@",response.suggestedFilename);
NSLog(@"%@",url.lastPathComponent);

6.  只要创建NSURLSession对象,在结束时都要释放,否则会造成内存泄漏

- (void)dealloc
{
    // 如果session设置代理的话,会有一个强引用.不会被释放.因此最后要释放session对象:调用下面两个方法都行.\
    否则会有内存泄漏.
    // finishTasksAndInvalidate
    [self.session invalidateAndCancel];
}

缺点:

1.如果用户点击暂停之后退出程序,那么需要把恢复下载的数据写一份到沙盒,代码复杂度更

2.如果用户在下载中途未保存恢复下载数据即退出程序,则不具备可操作性


代码:

//  Created by 朝阳 on 2017/12/18.
//  Copyright © 2017年 sunny. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic,strong) NSURLSession *session;

@end

@implementation ViewController

- (NSURLSession *)session
{
    if (!_session) {
        _session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    }
    return _session;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self delegateDownload];
}

// 使用block块的方式来下载数据
// 优点: 不需要手动将数据做沙盒缓存
// 缺点: 无法监听数据的下载进度
- (void)blockDownload
{
    //1. 确定请求的URL路径
    NSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/resources/images/minion_01.png"];
    //2. 创建请求
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    /**
     注意: 这个方法 会自动将请求的数据,保存到沙盒中: tmp 临时数据中
     4. 创建Task任务
     param location 数据保存到临时数据tmp中的路径
     param response 响应头   response.suggestedFilename 获取资源图片的名称
     param error 错误信息
     return downloadTask
     */
    NSURLSessionDownloadTask *downloadTask = [self.session downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        // 在子线程
        //4.1 拼接文件全路径
        NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename];
        //4.2 剪切文件到指定位置
        [[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:fullPath] error:nil];
        
        NSLog(@"%@",location);
        NSLog(@"%@",fullPath);
        NSLog(@"%@",response.suggestedFilename);
        NSLog(@"%@",url.lastPathComponent);
        
    }];
    
    //5. 执行任务
    [downloadTask resume];
}

// 使用代理的方式来下载数据
- (void)delegateDownload
{
    //1. 确定请求路径
    NSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/resources/images/minion_01.png"];
    //2. 创建请求
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    //3. 创建会话对象
    //4. 创建downloadTask
    NSURLSessionDownloadTask *downloadTask = [self.session downloadTaskWithRequest:request];
    //5. 执行task
    [downloadTask resume];
}

#pragma -mark NSURLSessionDownloadDelegate

/**
 写数据
 
 @param session 会话对象
 @param downloadTask 下载任务
 @param bytesWritten 本次写入的数据大小
 @param totalBytesWritten 下载的数据总大小
 @param totalBytesExpectedToWrite 文件总大小
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
    // 文件的下载进度
    NSLog(@"%f",1.0 * totalBytesWritten / totalBytesExpectedToWrite);
}

/**
 当恢复下载的时候调用该方法
 
 @param fileOffset 从什么地方下载
 @param expectedTotalBytes 文件总大小
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
    NSLog(@"%s, line = %d", __FUNCTION__, __LINE__);
}

/**
 当下载完成的时候调用
 
 @param location 文件的临时存储路径
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
    NSLog(@"%@",location);
    //1. 拼接cache路径
    NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
    //2. 剪切到指定位置
    [[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:fullPath] error:nil];
    NSLog(@"%@",fullPath);
}

/**
 请求结束时调用
 */
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    NSLog(@"didCompleteWithError");
}

- (void)dealloc
{
    // 如果session设置代理的话,会有一个强引用.不会被释放.因此最后要释放session对象:调用下面两个方法都行.\
    否则会有内存泄漏.
    // finishTasksAndInvalidate
    [self.session invalidateAndCancel];
}

@end


你可能感兴趣的:(iOS-多线程网络)