0922-网络 文件下载

------------------------------

工作中不要用NSURLConnection NSURLSession(可以更好的理解AFN)   用AFN(对这2个类分别做了封装)就可以了

掌握程度:     有的公司旧的项目还用NSURLConnection  自动异步   [NSURLConnection connectionWithRequest:request delegate:self]; 比sendAsync sync好 可以监听这个请求过程

1、知道md5就可以了

//  HMViewController.m

#import "HMViewController.h"
#import "MBProgressHUD+MJ.h"
#import "NSString+Hash.h"

@interface HMViewController ()
@property (weak, nonatomic) IBOutlet UITextField *username;
@property (weak, nonatomic) IBOutlet UITextField *pwd;
- (IBAction)login;
@end

@implementation HMViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.view endEditing:YES];
}

- (IBAction)login {
    // 1.用户名
    NSString *usernameText = self.username.text;
    if (usernameText.length == 0) {
        [MBProgressHUD showError:@"请输入用户名"];
        return;
    }
    
    // 2.密码
    NSString *pwdText = self.pwd.text;
    if (pwdText.length == 0) {
        [MBProgressHUD showError:@"请输入密码"];
        return;
    }
    
    // 增加蒙板
    [MBProgressHUD showMessage:@"正在拼命登录中...."];
    
    // 3.发送用户名和密码给服务器(走HTTP协议)
    // 创建一个URL : 请求路径
    NSURL *url = [NSURL URLWithString:@"http://192.168.15.172:8080/MJServer/login"];
    
    // 创建一个请求
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    
    // 5秒后算请求超时(默认60s超时)
    request.timeoutInterval = 15;
    
    request.HTTPMethod = @"POST";
    
#warning 对pwdText进行加密
    pwdText = [self MD5Reorder:pwdText];
    
    // 设置请求体
    NSString *param = [NSString stringWithFormat:@"username=%@&pwd=%@", usernameText, pwdText];
    
    NSLog(@"%@", param);
    
    // NSString --> NSData
    request.HTTPBody = [param dataUsingEncoding:NSUTF8StringEncoding];
    
    // 设置请求头信息
    [request setValue:@"iPhone 6" forHTTPHeaderField:@"User-Agent"];
    
    // 发送一个同步请求(在主线程发送请求)
    // queue :存放completionHandler这个任务
    NSOperationQueue *queue = [NSOperationQueue mainQueue];
    [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:
     ^(NSURLResponse *response, NSData *data, NSError *connectionError) {
         // 隐藏蒙板
         [MBProgressHUD hideHUD];
     
        // 这个block会在请求完毕的时候自动调用
        if (connectionError || data == nil) { // 一般请求超时就会来到这
            [MBProgressHUD showError:@"请求失败"];
            return;
        }
        
        // 解析服务器返回的JSON数据
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
        NSString *error = dict[@"error"];
        if (error) {
            [MBProgressHUD showError:error];
        } else {
            NSString *success = dict[@"success"];
            [MBProgressHUD showSuccess:success];
        }
     }];
}

/**
 *  MD5($pass.$salt)
 *
 *  @param text 明文
 *
 *  @return 加密后的密文
 */
- (NSString *)MD5Salt:(NSString *)text
{
    // 撒盐:随机地往明文中插入任意字符串
    NSString *salt = [text stringByAppendingString:@"aaa"];
    return [salt md5String];
}

/**
 *  MD5(MD5($pass))
 *
 *  @param text 明文
 *
 *  @return 加密后的密文
 */
- (NSString *)doubleMD5:(NSString *)text
{
    return [[text md5String] md5String];
}

/**
 *  先加密,后乱序
 *
 *  @param text 明文
 *
 *  @return 加密后的密文
 */
- (NSString *)MD5Reorder:(NSString *)text
{
    NSString *pwd = [text md5String];
    
    // 加密后pwd == 3f853778a951fd2cdf34dfd16504c5d8
    NSString *prefix = [pwd substringFromIndex:2];
    NSString *subfix = [pwd substringToIndex:2];
    
    // 乱序后 result == 853778a951fd2cdf34dfd16504c5d83f
    NSString *result = [prefix stringByAppendingString:subfix];
    
    NSLog(@"\ntext=%@\npwd=%@\nresult=%@", text, pwd, result);
    
    return result;
}
@end
View Code


2、掌握Reachability类 监听网络连接 发送到通知中心(以后用AFN):

通知中心添加observer:self     监听这个通知 kReachabilityChangedNotification 执行 netWorkConnectChange

Reachability -reachabilityForInternetConnection  -startNotifier  

netWorkConnectChange{

if([[Reachability reachabilityForLocalWiFi] currentReachabilityStatus] != NotReachable) return @"wifi";

if([[Reachability reachabilityForInternetConnection] currentReachabilityStatus] != NotReachable) return @"自带的3G或者4G";

}
- (void)dealloc
{
    [self.reachability stopNotifier];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

//
//  HMViewController.m

#import "HMViewController.h"
#import "Reachability.h"
#import "HMNetworkTool.h"

@interface HMViewController ()
@property (nonatomic, strong) Reachability *reachability;
@end

@implementation HMViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
//    UIProgressView
    
    // 监听网络状态发生改变的通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkStateChange) name:kReachabilityChangedNotification object:nil];
    
    // 获得Reachability对象
    self.reachability = [Reachability reachabilityForInternetConnection];
    // 开始监控网络
    [self.reachability startNotifier];

//    // 1.获得Reachability对象
//    Reachability *wifi = [Reachability reachabilityForLocalWiFi];
//    
//    // 2.获得Reachability对象的当前网络状态
//    NetworkStatus wifiStatus = wifi.currentReachabilityStatus;
//    if (wifiStatus != NotReachable) {
//        NSLog(@"是WIFI");
//    }
}

- (void)dealloc
{
    [self.reachability stopNotifier];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)networkStateChange
{
    NSLog(@"网络状态改变了");
    [self checkNetworkState];
}

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

/**
 *  监测网络状态
 */
- (void)checkNetworkState
{
    if ([HMNetworkTool isEnableWIFI]) {
        NSLog(@"WIFI环境");
    } else if ([HMNetworkTool isEnable3G]) {
        NSLog(@"手机自带网络");
    } else {
        NSLog(@"没有网络");
    }
}


@end
View Code
//
//  HMNetworkTool.m

#import "HMNetworkTool.h"
#import "Reachability.h"

@implementation HMNetworkTool
// 是否WIFI
+ (BOOL)isEnableWIFI {
    return ([[Reachability reachabilityForLocalWiFi] currentReachabilityStatus] != NotReachable);
}

// 是否3G
+ (BOOL)isEnable3G {
    return ([[Reachability reachabilityForInternetConnection] currentReachabilityStatus] != NotReachable);
}
@end
View Code

 
3、小文件下载 掌握  

//
//  HMViewController.m

#import "HMViewController.h"
@interface HMViewController ()
@end
@implementation HMViewController
- (void)viewDidLoad
{
    [super viewDidLoad];
    // 下载小文件的方式
    // 1.NSData dataWithContentsOfURL
    // 2.NSURLConnection
}

// 1.NSData dataWithContentsOfURL
- (void)downloadFile
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 其实这就是一个GET请求
        NSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/resources/images/minion_01.png"];
        NSData *data = [NSData dataWithContentsOfURL:url];
        NSLog(@"%d", data.length);
    });
}

// 2.NSURLConnection
- (void)downloadFile2
{
    NSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/resources/images/minion_01.png"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        NSLog(@"%d", data.length);
    }];
}

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

@end
View Code


4、大文件下载不合理 不掌握  用一个变量接收完整的文件数据  内存占用太大

5、大文件下载 (合理 掌握)

0、[NSURLConnection connectionWithRequest: delegate:] 监听到3个步骤 让代理执行

1、-connection didReceiveResponse  ,   -connection   didReceiveData   ,  -connection connectionDidFinishLoading

-connection didReceiveResponse  : NSFileManager 创建空文件,  [NSFileHandle fileHandleForWritingAtPath:filepath];

-connection   -didReceiveData  : NSFileHandle seekToEndOfFile(移动到文件尾部)  writeData

-connection connectionDidFinishLoading  : 停止并清空NSFileHandle   NSFileHandle closeFile   NSFileHandle nil;

 

//
//  HMViewController.m

#import "HMViewController.h"
#import "DACircularProgressView.h"

@interface HMViewController () <NSURLConnectionDataDelegate>
/**
 *  用来写数据的文件句柄对象
 */
@property (nonatomic, strong) NSFileHandle *writeHandle;
/**
 *  文件的总大小
 */
@property (nonatomic, assign) long long totalLength;
/**
 *  当前已经写入的文件大小
 */
@property (nonatomic, assign) long long currentLength;

@property (nonatomic, weak) DACircularProgressView *circleView;
@end

@implementation HMViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    DACircularProgressView *circleView = [[DACircularProgressView alloc] init];
    circleView.frame = CGRectMake(100, 50, 100, 100);
    circleView.progressTintColor = [UIColor redColor];
    circleView.trackTintColor = [UIColor blueColor];
    circleView.progress = 0.01;
    [self.view addSubview:circleView];
    self.circleView = circleView;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // 1.URL
    NSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/resources/music.zip"];
    
    // 2.请求
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
    // 3.下载(创建完conn对象后,会自动发起一个异步请求)
    [NSURLConnection connectionWithRequest:request delegate:self];
}

#pragma mark - NSURLConnectionDataDelegate代理方法
/**
 *  请求失败时调用(请求超时、网络异常)
 *
 *  @param error      错误原因
 */
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"didFailWithError");
}

/**
 *  1.接收到服务器的响应就会调用
 *
 *  @param response   响应
 */
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    // 文件路径
    NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    NSString *filepath = [caches stringByAppendingPathComponent:@"videos.zip"];
    
    // 创建一个空的文件 到 沙盒中
    NSFileManager *mgr = [NSFileManager defaultManager];
    [mgr createFileAtPath:filepath contents:nil attributes:nil];
    
    // 创建一个用来写数据的文件句柄
    self.writeHandle = [NSFileHandle fileHandleForWritingAtPath:filepath];
    
    // 获得文件的总大小
    self.totalLength = response.expectedContentLength;
}

/**
 *  2.当接收到服务器返回的实体数据时调用(具体内容,这个方法可能会被调用多次)
 *
 *  @param data       这次返回的数据
 */
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    // 移动到文件的最后面
    [self.writeHandle seekToEndOfFile];
    
    // 将数据写入沙盒
    [self.writeHandle writeData:data];
    
    // 累计文件的长度
    self.currentLength += data.length;
    
    NSLog(@"下载进度:%f", (double)self.currentLength/ self.totalLength);
    self.circleView.progress = (double)self.currentLength/ self.totalLength;
}

/**
 *  3.加载完毕后调用(服务器的数据已经完全返回后)
 */
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    self.currentLength = 0;
    self.totalLength = 0;
    
    // 关闭文件
    [self.writeHandle closeFile];
    self.writeHandle = nil;
}
@end
View Code


6、断点下载   暂停后再开始 指定下载起始位置为记录的下载位置   请求头加range   点击暂停时候 self.conn cancel   self.conn=nil

自己补充当下次开始下载的时候从沙盒取出currentLength

    sender.selected = !sender.isSelected;

    if (sender.selected) { // 继续(开始)下载
        // 1.URL
        NSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/resources/videos.zip"];
        
        // 2.请求
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
        
        // 设置请求头
        NSString *range = [NSString stringWithFormat:@"bytes=%lld-", self.currentLength];
        [request setValue:range forHTTPHeaderField:@"Range"];
        
        // 3.下载(创建完conn对象后,会自动发起一个异步请求)
        self.conn = [NSURLConnection connectionWithRequest:request delegate:self];
    } else { // 暂停
        [self.conn cancel];
        self.conn = nil;
    }

 


明天的多线程断点下载  以后拿来用就可以了   不需要掌握的   太复杂

//  HMViewController.m

#import "HMViewController.h"
#import "DACircularProgressView.h"

@interface HMViewController () <NSURLConnectionDataDelegate>
- (IBAction)download:(UIButton *)sender;

/**
 *  用来写数据的文件句柄对象
 */
@property (nonatomic, strong) NSFileHandle *writeHandle;
/**
 *  文件的总大小
 */
@property (nonatomic, assign) long long totalLength;
/**
 *  当前已经写入的文件大小
 */
@property (nonatomic, assign) long long currentLength;

/**
 *  连接对象
 */
@property (nonatomic, strong) NSURLConnection *conn;

@property (nonatomic, weak) DACircularProgressView *circleView;
@end

@implementation HMViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    DACircularProgressView *circleView = [[DACircularProgressView alloc] init];
    circleView.frame = CGRectMake(100, 50, 100, 100);
    circleView.progressTintColor = [UIColor redColor];
    circleView.trackTintColor = [UIColor blueColor];
    circleView.progress = 0.0000001;
    [self.view addSubview:circleView];
    self.circleView = circleView;
}

#pragma mark - NSURLConnectionDataDelegate代理方法
/**
 *  请求失败时调用(请求超时、网络异常)
 *
 *  @param error      错误原因
 */
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"didFailWithError");
}

/**
 *  1.接收到服务器的响应就会调用
 *
 *  @param response   响应
 */
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    if (self.currentLength) return;
    
    // 文件路径
    NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    NSString *filepath = [caches stringByAppendingPathComponent:@"videos.zip"];
    
    // 创建一个空的文件 到 沙盒中
    NSFileManager *mgr = [NSFileManager defaultManager];
    [mgr createFileAtPath:filepath contents:nil attributes:nil];
    
    // 创建一个用来写数据的文件句柄
    self.writeHandle = [NSFileHandle fileHandleForWritingAtPath:filepath];
    
    // 获得文件的总大小
    self.totalLength = response.expectedContentLength;
}

/**
 *  2.当接收到服务器返回的实体数据时调用(具体内容,这个方法可能会被调用多次)
 *
 *  @param data       这次返回的数据
 */
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    // 移动到文件的最后面
    [self.writeHandle seekToEndOfFile];
    
    // 将数据写入沙盒
    [self.writeHandle writeData:data];
    
    // 累计文件的长度
    self.currentLength += data.length;
    
    self.circleView.progress = (double)self.currentLength/ self.totalLength;
}

/**
 *  3.加载完毕后调用(服务器的数据已经完全返回后)
 */
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    self.currentLength = 0;
    self.totalLength = 0;
    
    // 关闭文件
    [self.writeHandle closeFile];
    self.writeHandle = nil;
}

- (IBAction)download:(UIButton *)sender {
    // 状态取反
    sender.selected = !sender.isSelected;
    
    // 断点续传
    // 断点下载
    
    if (sender.selected) { // 继续(开始)下载
        // 1.URL
        NSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/resources/videos.zip"];
        
        // 2.请求
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
        
        // 设置请求头
        NSString *range = [NSString stringWithFormat:@"bytes=%lld-", self.currentLength];
        [request setValue:range forHTTPHeaderField:@"Range"];
        
        // 3.下载(创建完conn对象后,会自动发起一个异步请求)
        self.conn = [NSURLConnection connectionWithRequest:request delegate:self];
    } else { // 暂停
        [self.conn cancel];
        self.conn = nil;
    }
}
@end
View Code

 


7、NSURLSession  ios7新推出的  目的是为了取代NSURLConnection     自动写到沙盒temp文件里

session 交给代理来监听下载进度 。   [session  dataTask]  [dataTask start]。[session downloadTask]  [task start]

NSURLSession与NSURLConnection比较如下:

[NSURLRequest requestWithURL:URL];
[NSURLConnection connectionWithRequest:request delegate:self]

等同于下面4个

NSURLSessionConfiguration *cfg = [NSURLSessionConfiguration defaultSessionConfiguration];

    NSURLSession *session = [NSURLSession sessionWithConfiguration:cfg delegate:self delegateQueue:[NSOperationQueue mainQueue]];

    NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url];

[task resume];


NSURLSessionDownloadDelegate
1、URLSession   downloadTask -didFinishDownloadingToURL(NSURL *)location  已经下到temp里(location.path) 

获取 temp临时文件路 ( location.path )

移动到的文件路径 caches/下载的文件名( downloadTask.response.suggestedFilename )

NSFileManager移动到 

2、URLSession   downloadTask -didResumeAtOffset 恢复下载时候调用  一般永不上这个方法

3、URLSession downloadTask -didWriteData:(int64_t)bytesWritten 这次下载的长度 已经下载的长度  总长度

 

 


[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^ 相当于下面的 NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url completionHandler [task resume]; 或者 NSURLSessionDataTask *task = [session dataTaskWithRequest [task resume];

 

 

//
//  HMViewController.m

#import "HMViewController.h"

@interface HMViewController () <NSURLSessionDownloadDelegate>

@end

@implementation HMViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

// 任务:任何请求都是一个任务
// NSURLSessionDataTask : 普通的GET\POST请求
// NSURLSessionDownloadTask : 文件下载
// NSURLSessionUploadTask : 文件上传
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self downloadTask2];
}

- (void)downloadTask2
{
    NSURLSessionConfiguration *cfg = [NSURLSessionConfiguration defaultSessionConfiguration];
    
    // 1.得到session对象
    NSURLSession *session = [NSURLSession sessionWithConfiguration:cfg delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    
    // 2.创建一个下载task
    NSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/resources/test.mp4"];
    NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url];
    
    // 3.开始任务
    [task resume];
    
    // 如果给下载任务设置了completionHandler这个block,也实现了下载的代理方法,优先执行block
}

#pragma mark - NSURLSessionDownloadDelegate
/**
 *  下载完毕后调用
 *
 *  @param location     临时文件的路径(下载好的文件)
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
    // location : 临时文件的路径(下载好的文件)
    
    NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    // response.suggestedFilename : 建议使用的文件名,一般跟服务器端的文件名一致
    
    NSString *file = [caches stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
    
    // 将临时文件剪切或者复制Caches文件夹
    NSFileManager *mgr = [NSFileManager defaultManager];
    
    // AtPath : 剪切前的文件路径
    // ToPath : 剪切后的文件路径
    [mgr moveItemAtPath:location.path toPath:file error:nil];
}

/**
 *  恢复下载时调用
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{

}


/**
 *  每当下载完(写完)一部分时就会调用(可能会被调用多次)
 *
 *  @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
{
    double progress = (double)totalBytesWritten / totalBytesExpectedToWrite;
    NSLog(@"下载进度---%f", progress);
}

#pragma mark ------------------------------------------------------------------
/**
 *  下载任务:不能看到下载进度
 */
- (void)downloadTask
{
    // 1.得到session对象
    NSURLSession *session = [NSURLSession sharedSession];
    
    // 2.创建一个下载task
    NSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/resources/test.mp4"];
    NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
        // location : 临时文件的路径(下载好的文件)
        
        NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
        // response.suggestedFilename : 建议使用的文件名,一般跟服务器端的文件名一致
        NSString *file = [caches stringByAppendingPathComponent:response.suggestedFilename];
        
        // 将临时文件剪切或者复制Caches文件夹
        NSFileManager *mgr = [NSFileManager defaultManager];
        
        // AtPath : 剪切前的文件路径
        // ToPath : 剪切后的文件路径
        [mgr moveItemAtPath:location.path toPath:file error:nil];
    }];
    
    // 3.开始任务
    [task resume];
}

- (void)dataTask
{
    // 1.得到session对象
    NSURLSession *session = [NSURLSession sharedSession];
    
    // 2.创建一个task,任务
    //    NSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/video"];
    //    NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    //        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
    //        NSLog(@"----%@", dict);
    //    }];
    
    NSURL *url = [NSURL URLWithString:@"http://192.168.15.172:8080/MJServer/login"];
    
    // 创建一个请求
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = @"POST";
    // 设置请求体
    request.HTTPBody = [@"username=123&pwd=123" dataUsingEncoding:NSUTF8StringEncoding];
    
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
        NSLog(@"----%@", dict);
    }];
    
    // 3.开始任务
    [task resume];
}

@end
View Code

 --------------------------------------

8、NSURLSession文件断点续传   完整的 以后可以用这个

[self.task resume];表示开始任务  而不是恢复任务

self resume111才便是开始回复

多线程断点下载 复杂度极高  没有视频解说   只说了思路:   先创建一个大的文件   四个线程确定每个线程的下载 range  这样下载完就直接是一个完整的文件了

- (IBAction)download:(UIButton *)sender {
    // 按钮状态取反
    sender.selected = !sender.isSelected;
    
    if (self.task == nil) { // 开始(继续)下载
        if (self.resumeData) { // 恢复
            [self resume111];
        } else { // 开始
            [self startOriginTask111];
        }
    } else { // 暂停
        [self pause111];
    }
}
/**
 *  恢复(继续)
 */
- (void)resume111
{
    // 传入上次暂停下载返回的数据,就可以恢复下载
    self.task = [self.session downloadTaskWithResumeData:self.resumeData];
    
    // 开始任务
    [self.task resume];
    
    // 清空
    self.resumeData = nil;
}

/**
 *  暂停
 */
- (void)pause111
{
    __weak typeof(self) vc = self;
    [self.task cancelByProducingResumeData:^(NSData *resumeData) {
        //  resumeData : 包含了继续下载的开始位置\下载的url
        vc.resumeData = resumeData;
        vc.task = nil;
    }];
}

 

 

//
//  HMViewController.m

#import "HMViewController.h"

@interface HMViewController () <NSURLSessionDownloadDelegate, NSURLSessionDataDelegate>
@property (weak, nonatomic) IBOutlet UIProgressView *progressView;
- (IBAction)download:(UIButton *)sender;

@property (nonatomic, strong) NSURLSessionDownloadTask *task;
@property (nonatomic, strong) NSData *resumeData;
@property (nonatomic, strong) NSURLSession *session;
@end

@implementation HMViewController

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

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
}

- (IBAction)download:(UIButton *)sender {
    // 按钮状态取反
    sender.selected = !sender.isSelected;
    
    if (self.task == nil) { // 开始(继续)下载
        if (self.resumeData) { // 恢复
            [self resume111];
        } else { // 开始
            [self startOriginTask111];
        }
    } else { // 暂停
        [self pause111];
    }
}

/**
 *  从零开始
 */
- (void)startOriginTask111
{
    // 1.创建一个下载任务
    NSURL *url = [NSURL URLWithString:@"http://192.168.15.172:8080/MJServer/resources/videos/minion_01.mp4"];
    self.task = [self.session downloadTaskWithURL:url];
    
    // 2.开始任务
    [self.task resume];
}

/**
 *  恢复(继续)
 */
- (void)resume111
{
    // 传入上次暂停下载返回的数据,就可以恢复下载
    self.task = [self.session downloadTaskWithResumeData:self.resumeData];
    
    // 开始任务
    [self.task resume];
    
    // 清空
    self.resumeData = nil;
}

/**
 *  暂停
 */
- (void)pause111
{
    __weak typeof(self) vc = self;
    [self.task cancelByProducingResumeData:^(NSData *resumeData) {
        //  resumeData : 包含了继续下载的开始位置\下载的url
        vc.resumeData = resumeData;
        vc.task = nil;
    }];
}

#pragma mark - NSURLSessionDownloadDelegate
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{
    NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    // response.suggestedFilename : 建议使用的文件名,一般跟服务器端的文件名一致
    NSString *file = [caches stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
    
    // 将临时文件剪切或者复制Caches文件夹
    NSFileManager *mgr = [NSFileManager defaultManager];
    
    // AtPath : 剪切前的文件路径
    // ToPath : 剪切后的文件路径
    [mgr moveItemAtPath:location.path toPath:file error:nil];
}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
      didWriteData:(int64_t)bytesWritten
 totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
    NSLog(@"获得下载进度--%@", [NSThread currentThread]);
    // 获得下载进度
    self.progressView.progress = (double)totalBytesWritten / totalBytesExpectedToWrite;
}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
 didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes
{
    
}

//- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
//{
//
//}
//
//- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
//{
//
//}
@end
View Code

 

 

 

 

————————————————————————————————————————————————————————————

MD5方法在我的微云里


—————————

Reachability   我的微云里有这个框架

创建Reachablity对象并调用 start方法   并作为控制器属性  不让这个对象消失

这个对象会不停监听网络状态并发出notification 到通知中心

我们在通知中心添加一个observer 也就是self

我们拿到通知 做相应的操作

控制器 dealloc 用通知中心移除observer self    reachability对象 stop停止发通知

 

掌握Reachability类(苹果开放了实现方法的类)有助于了解AFN  AFN更好用   

Reachability.m里有release操作   所以需要

xcode->项目-》build phases-》compile sources Reachability.m 添加上 -fno-objc-arc



Reachability(苹果开放了实现方法的类  有release代码  所以需要  

xcode->项目-》build phases-》compile sources Reachability.m 添加上 -fno-objc-arc

)   存放到第三方框架里

-----------

小文件文件下载

NSURLConnection可发 sendAsync异步发送请求    回到某个线程:queue  做什么操作  用于小文件下载 因为大文件用户可能断网
———————

大文件下载 NSURLConnection    合理部分   

NSURLConnection connectionWithRequest: delegate:    NSURLConnection接收到数据会让代理调用相应的方法

代理需要实现  NSURLConnection写的代理协议

 <NSURLConnectionDataDelegate> delegate

NSURLConnection默认都是异步请求

————————

断点下载

——————————

NSURLSession  边下载边写数据  

对比NSURLConnection  NSURLSession不用设计属性计算文件下载多少

NSURLSessionUploadTask 一般的HTTP服务器不支持苹果的这个功能  所以不需要掌握

int64_4 相当于64位的long long类型

 

posted @ 2016-03-19 13:59  海龙王来了  阅读(173)  评论(0编辑  收藏  举报
友情链接:废钢破碎机  带式压滤机