iOS网络文件下载

此方法内导入了Category(加密工具包)文件包,和MBProgressHud(弹出遮盖效果)


- (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.1.127:8080/ZWServer/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






检测网络状态第三方包(Reachability)
@implementation HMViewController


- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 监听网络状态发生改变的通知
    [[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


//下载小文件方法
@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://192.168.1.127:8080/ZWServer/resources/images/minion_01.png"];
        NSData *data = [NSData dataWithContentsOfURL:url];
        NSLog(@"%d", data.length);
    });
}


// 2.NSURLConnection
- (void)downloadFile2
{
    NSURL *url = [NSURL URLWithString:@"http://192.168.1.127:8080/ZWServer/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




大文件的下载方式(不太合理的方式)下面有合理的方式
@interface HMViewController () <NSURLConnectionDataDelegate>
@property (weak, nonatomic) IBOutlet UIProgressView *progressView;
@property (nonatomic, strong) NSMutableData *fileData;


/**
 *  文件的总长度
 */
@property (nonatomic, assign) long long totalLength;


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


@implementation HMViewController


- (void)viewDidLoad
{
    [super viewDidLoad];
    
    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)download
{
    // 1.URL
    NSURL *url = [NSURL URLWithString:@"http://192.168.1.127:8080/ZWServer/resources/videos.zip"];
    
    // 2.请求
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
    // 3.下载(创建完conn对象后,会自动发起一个异步请求)
    [NSURLConnection connectionWithRequest:request delegate:self];
    
//    [[NSURLConnection alloc] initWithRequest:request delegate:self];
//    [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
    
//    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
//    [conn start];
}


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


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


/**
 *  1.接收到服务器的响应就会调用
 *
 *  @param response   响应
 */
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    NSLog(@"didReceiveResponse");
    
    // 初始化数据
    self.fileData = [NSMutableData data];
    
    // 取出文件的总长度
//    NSHTTPURLResponse *resp = (NSHTTPURLResponse *)response;
//    long long fileLength = [resp.allHeaderFields[@"Content-Length"] longLongValue];
    self.totalLength = response.expectedContentLength;
}


/**
 *  2.当接收到服务器返回的实体数据时调用(具体内容,这个方法可能会被调用多次)
 *
 *  @param data       这次返回的数据
 */
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    // 拼接数据
    [self.fileData appendData:data];
    
    // 设置进度值
    // 0 ~ 1
//    self.progressView.progress = (double)self.fileData.length / self.totalLength;
    self.circleView.progress = (double)self.fileData.length / self.totalLength;
}


/**
 *  3.加载完毕后调用(服务器的数据已经完全返回后)
 */
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSLog(@"connectionDidFinishLoading");
    
    // 拼接文件路径
    NSString *cache = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    NSString *file = [cache stringByAppendingPathComponent:@"videos.zip"];
    
    // 写到沙盒中
    [self.fileData writeToFile:file atomically:YES];
}


@end




合理的大文件下载方式
@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://192.168.1.127:8080/ZWServer/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






断点下载文件
@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://192.168.1.127:8080/ZWServer/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










普通的GET\POST请求下载(下载池)


@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://192.168.1.127:8080/ZWServer/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://192.168.1.127:8080/ZWServer/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://192.168.1.127:8080/ZWServer/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.1.127:8080/ZWServer/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



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值