文件下载
使用NSURLSessionDownloadTask下载文件的过程与前面差不多,需要注意的是文件下载文件之后会自动保存到一个临时目录,需要开发人员自己将此文件重新放到其他指定的目录中。
-(void)downloadFile{
//1.创建url
NSString *fileName=@"1.jpg";
NSString *urlStr=[NSString stringWithFormat: @"http://192.168.1.208/FileDownload.aspx?file=%@",fileName];
urlStr =[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url=[NSURL URLWithString:urlStr];
//2.创建请求
NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:url];
//3.创建会话(这里使用了一个全局会话)并且启动任务
NSURLSession *session=[NSURLSession sharedSession];
NSURLSessionDownloadTask *downloadTask=[session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
if (!error) {
//注意location是下载后的临时保存路径,需要将它移动到需要保存的位置
NSError *saveError;
NSString *cachePath=[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSString *savePath=[cachePath stringByAppendingPathComponent:fileName];
NSLog(@"%@",savePath);
NSURL *saveUrl=[NSURL fileURLWithPath:savePath];
[[NSFileManager defaultManager] copyItemAtURL:location toURL:saveUrl error:&saveError];
if (!saveError) {
NSLog(@"save sucess.");
}else{
NSLog(@"error is :%@",saveError.localizedDescription);
}
}else{
NSLog(@"error is :%@",error.localizedDescription);
}
}];
[downloadTask resume];
}
会话
NSURLConnection通过全局状态来管理cookies、认证信息等公共资源,这样如果遇到两个连接需要使用不同的资源配置情况时就无法解决了,但是这个问题在NSURLSession中得到了解决。NSURLSession同时对应着多个连接,会话通过工厂方法来创建,同一个会话中使用相同的状态信息。NSURLSession支持进程三种会话:
defaultSessionConfiguration
:进程内会话(默认会话),用硬盘来缓存数据。ephemeralSessionConfiguration
:临时的进程内会话(内存),不会将cookie、缓存储存到本地,只会放到内存中,当应用程序退出后数据也会消失。backgroundSessionConfiguration
:后台会话,相比默认会话,该会话会在后台开启一个线程进行网络数据处理。
下面将通过一个文件下载功能对两种会话进行演示,在这个过程中也会用到任务的代理方法对上传操作进行更加细致的控制。下面先看一下使用默认会话下载文件,代码中演示了如何通过NSURLSessionConfiguration进行会话配置,如果通过代理方法进行文件下载进度展示(类似于前面中使用NSURLConnection代理方法,其实下载并未分段,如果需要分段需要配合后台进行),同时在这个过程中可以准确控制任务的取消、挂起和恢复。
//
// KCMainViewController.m
// URLSession
//
// Created by Kenshin Cui on 14-03-23.
// Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//
#import "KCMainViewController.h"
@interface KCMainViewController ()<NSURLSessionDownloadDelegate>{
UITextField *_textField;
UIProgressView *_progressView;
UILabel *_label;
UIButton *_btnDownload;
UIButton *_btnCancel;
UIButton *_btnSuspend;
UIButton *_btnResume;
NSURLSessionDownloadTask *_downloadTask;
}
@end
@implementation KCMainViewController
#pragma mark - UI方法
- (void)viewDidLoad {
[super viewDidLoad];
[self layoutUI];
}
#pragma mark 界面布局
-(void)layoutUI{
//地址栏
_textField=[[UITextField alloc]initWithFrame:CGRectMake(10, 50, 300, 25)];
_textField.borderStyle=UITextBorderStyleRoundedRect;
_textField.textColor=[UIColor colorWithRed:0 green:146/255.0 blue:1.0 alpha:1.0];
_textField.text=@"[Objective-C.程序设计(第4版)].(斯蒂芬).林冀等.扫描版[电子书www.minxue.net].pdf";
[self.view addSubview:_textField];
//进度条
_progressView=[[UIProgressView alloc]initWithFrame:CGRectMake(10, 100, 300, 25)];
[self.view addSubview:_progressView];
//状态显示
_label=[[UILabel alloc]initWithFrame:CGRectMake(10, 130, 300, 25)];
_label.textColor=[UIColor colorWithRed:0 green:146/255.0 blue:1.0 alpha:1.0];
[self.view addSubview:_label];
//下载按钮
_btnDownload=[[UIButton alloc]initWithFrame:CGRectMake(20, 500, 50, 25)];
[_btnDownload setTitle:@"下载" forState:UIControlStateNormal];
[_btnDownload setTitleColor:[UIColor colorWithRed:0 green:146/255.0 blue:1.0 alpha:1.0] forState:UIControlStateNormal];
[_btnDownload addTarget:self action:@selector(downloadFile) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_btnDownload];
//取消按钮
_btnCancel=[[UIButton alloc]initWithFrame:CGRectMake(100, 500, 50, 25)];
[_btnCancel setTitle:@"取消" forState:UIControlStateNormal];
[_btnCancel setTitleColor:[UIColor colorWithRed:0 green:146/255.0 blue:1.0 alpha:1.0] forState:UIControlStateNormal];
[_btnCancel addTarget:self action:@selector(cancelDownload) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_btnCancel];
//挂起按钮
_btnSuspend=[[UIButton alloc]initWithFrame:CGRectMake(180, 500, 50, 25)];
[_btnSuspend setTitle:@"挂起" forState:UIControlStateNormal];
[_btnSuspend setTitleColor:[UIColor colorWithRed:0 green:146/255.0 blue:1.0 alpha:1.0] forState:UIControlStateNormal];
[_btnSuspend addTarget:self action:@selector(suspendDownload) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_btnSuspend];
//恢复按钮
_btnResume=[[UIButton alloc]initWithFrame:CGRectMake(260, 500, 50, 25)];
[_btnResume setTitle:@"恢复" forState:UIControlStateNormal];
[_btnResume setTitleColor:[UIColor colorWithRed:0 green:146/255.0 blue:1.0 alpha:1.0] forState:UIControlStateNormal];
[_btnResume addTarget:self action:@selector(resumeDownload) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_btnResume];
}
#pragma mark 设置界面状态
-(void)setUIStatus:(int64_t)totalBytesWritten expectedToWrite:(int64_t)totalBytesExpectedToWrite{
dispatch_async(dispatch_get_main_queue(), ^{
_progressView.progress=(float)totalBytesWritten/totalBytesExpectedToWrite;
if (totalBytesWritten==totalBytesExpectedToWrite) {
_label.text=@"下载完成";
[UIApplication sharedApplication].networkActivityIndicatorVisible=NO;
_btnDownload.enabled=YES;
}else{
_label.text=@"正在下载...";
[UIApplication sharedApplication].networkActivityIndicatorVisible=YES;
}
});
}
#pragma mark 文件下载
-(void)downloadFile{
//1.创建url
NSString *fileName=_textField.text;
NSString *urlStr=[NSString stringWithFormat: @"http://192.168.1.208/FileDownload.aspx?file=%@",fileName];
urlStr =[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url=[NSURL URLWithString:urlStr];
//2.创建请求
NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:url];
//3.创建会话
//默认会话
NSURLSessionConfiguration *sessionConfig=[NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.timeoutIntervalForRequest=5.0f;//请求超时时间
sessionConfig.allowsCellularAccess=true;//是否允许蜂窝网络下载(2G/3G/4G)
//创建会话
NSURLSession *session=[NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];//指定配置和代理
_downloadTask=[session downloadTaskWithRequest:request];
[_downloadTask resume];
}
#pragma mark 取消下载
-(void)cancelDownload{
[_downloadTask cancel];
}
#pragma mark 挂起下载
-(void)suspendDownload{
[_downloadTask suspend];
}
#pragma mark 恢复下载下载
-(void)resumeDownload{
[_downloadTask resume];
}
#pragma mark - 下载任务代理
#pragma mark 下载中(会多次调用,可以记录下载进度)
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
[self setUIStatus:totalBytesWritten expectedToWrite:totalBytesExpectedToWrite];
}
#pragma mark 下载完成
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{
NSError *error;
NSString *cachePath=[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSString *savePath=[cachePath stringByAppendingPathComponent:_textField.text];
NSLog(@"%@",savePath);
NSURL *saveUrl=[NSURL fileURLWithPath:savePath];
[[NSFileManager defaultManager] copyItemAtURL:location toURL:saveUrl error:&error];
if (error) {
NSLog(@"Error is:%@",error.localizedDescription);
}
}
#pragma mark 任务完成,不管是否下载成功
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
[self setUIStatus:0 expectedToWrite:0];
if (error) {
NSLog(@"Error is:%@",error.localizedDescription);
}
}
@end
02.Session下载
- //
- // MJViewController.m
- // 02.Session下载
- //
- // Created by apple on 14-4-30.
- // Copyright (c) 2014年 itcast. All rights reserved.
- //
- #import "MJViewController.h"
- @interface MJViewController () <NSURLSessionDownloadDelegate>
- @property (weak, nonatomic) IBOutlet UIImageView *imageView;
- @end
- /**
- // 下载进度跟进
- - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
- didWriteData:(int64_t)bytesWritten
- totalBytesWritten:(int64_t)totalBytesWritten
- totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;
- didWriteData totalBytesWritten totalBytesExpectedToWrite
- 本次写入的字节数 已经写入的字节数 预期下载的文件大小
- // 完成下载
- - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
- didFinishDownloadingToURL:(NSURL *)location;
- */
- @implementation MJViewController
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- [self downloadTask];
- }
- #pragma mark - 下载(GET)
- - (void)downloadTask
- {
- // 1. URL
- NSURL *url = [NSURL URLWithString:@"http://localhost/itcast/images/head1.png"];
- // 2. Request
- NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:2.0];
- // 3. Session
- NSURLSession *session = [NSURLSession sharedSession];
- // 4. download
- [[session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
- // 下载的位置,沙盒中tmp目录中的临时文件,会被及时删除
- NSLog(@"下载完成 %@ %@", location, [NSThread currentThread]);
- /**
- document 备份,下载的文件不能放在此文件夹中
- cache 缓存的,不备份,重新启动不会被清空,如果缓存内容过多,可以考虑新建一条线程检查缓存目录中的文件大小,自动清理缓存,给用户节省控件
- tmp 临时,不备份,不缓存,重新启动iPhone,会自动清空
- */
- // 直接通过文件名就可以加载图像,图像会常驻内存,具体的销毁有系统负责
- // [UIImage imageNamed:@""];
- dispatch_async(dispatch_get_main_queue(), ^{
- // 从网络下载下来的是二进制数据
- NSData *data = [NSData dataWithContentsOfURL:location];
- // 这种方式的图像会自动释放,不占据内存,也不需要放在临时文件夹中缓存
- // 如果用户需要,可以提供一个功能,保存到用户的相册即可
- UIImage *image = [UIImage imageWithData:data];
- self.imageView.image = image;
- });
- }] resume];
- // [task resume];
- }