#import "ViewController.h"緩存
#import "AppDelegate.h"服務器
@interface ViewController ()網絡
@property (nonatomic,strong)UIImageView *imageView;session
@property (nonatomic,strong)UIProgressView *progressIndicator;app
@property (nonatomic,strong)NSURLSession *urlSession; // 普通會話async
@property (nonatomic,strong)NSURLSession *backgroundSession; // 後臺會話ide
@property (nonatomic,strong)NSURLSessionDownloadTask *sessionDownloadTask; // 下載Task編碼
@property (nonatomic,strong)NSURLSessionDownloadTask *resumableTask; // 恢復下載Taskatom
@property (nonatomic,strong)NSURLSessionDownloadTask *backgroundTask; // 後臺下載Taskurl
@property (nonatomic,strong)NSData *partialData; // 下載的局部數據
@property (copy, nonatomic) MyBlock backgroundURLSessionCompletionHandler;
@end
@implementation ViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad{
[super viewDidLoad];
self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 64, 320, 300)];
[self.view addSubview:_imageView];
self.progressIndicator = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
_progressIndicator.frame = CGRectMake(50, 500, 220, 50);
[self.view addSubview:_progressIndicator];
UIButton *cancleButton = [UIButton buttonWithType:UIButtonTypeSystem];
cancleButton.frame = CGRectMake(120, 400, 40, 40);
[cancleButton setTitle:@"取消" forState:UIControlStateNormal];
[cancleButton addTarget:self action:@selector(didClickCancleButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:cancleButton];
UIButton *downloadButton = [UIButton buttonWithType:UIButtonTypeSystem];
downloadButton.frame = CGRectMake(20, 400, 40, 40);
[downloadButton setTitle:@"下載" forState:UIControlStateNormal];
[downloadButton addTarget:self action:@selector(didClickDownloadButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:downloadButton];
UIButton *uploadButton = [UIButton buttonWithType:UIButtonTypeSystem];
uploadButton.frame = CGRectMake(70, 400, 40, 40);
[uploadButton setTitle:@"上傳" forState:UIControlStateNormal];
[uploadButton addTarget:self action:@selector(didClickUploadButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:uploadButton];
UIButton *resumableButton = [UIButton buttonWithType:UIButtonTypeSystem];
resumableButton.frame = CGRectMake(180, 400, 40, 40);
[resumableButton setTitle:@"恢復" forState:UIControlStateNormal];
[resumableButton addTarget:self action:@selector(didClickResuableButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:resumableButton];
UIButton *backgroundLoadButton = [UIButton buttonWithType:UIButtonTypeSystem];
backgroundLoadButton.frame = CGRectMake(220, 400, 80, 40);
[backgroundLoadButton setTitle:@"後臺下載" forState:UIControlStateNormal];
[backgroundLoadButton addTarget:self action:@selector(didClickBackgroundButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:backgroundLoadButton];
#pragma mark - 若是咱們須要利用NSURLSession進行數據傳輸咱們須要:
/**
* 建立一個NSURLSessionConfiguration,用於建立NSSession時設置工做模式(3種)
* (1)通常模式(default):工做模式相似於原來的NSURLConnection,可使用緩存的Cache,Cookie,鑑權。
* (2)及時模式(ephemeral):不使用緩存的Cache,Cookie,鑑權。
* (3)後臺模式(background):在後臺完成上傳下載,建立Configuration對象的時候須要給一個NSString的ID用於追蹤完成工做的Session是哪個
*/
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
/**
* @網絡設置:參考NSURLConnection中的設置項
* 兩種建立方法(目前不太懂什麼區別)
* (1)就是根據剛纔建立的Configuration建立一個Session,系統默認建立一個新的OperationQueue處理Session的消息
* (2)能夠設定回調的delegate(注意這個回調delegate會被強引用),而且能夠設定delegate在哪一個OperationQueue回調,若是咱們將其
* 設置爲[NSOperationQueue mainQueue]就能在主線程進行回調很是的方便
*/
//NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig];
self.urlSession = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]];
NSURL *url = [NSURL URLWithString:@"http://www.bizhiwa.com/uploads/allimg/2012-01/22021207-1-311536.jpg"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
/**
* NSURLSessionUploadTask:上傳用的Task,傳完之後不會再下載返回結果;
* NSURLSessionDownloadTask:下載用的Task;
* NSURLSessionDataTask:能夠上傳內容,上傳完成後再進行下載。
*/
self.sessionDownloadTask = [self.urlSession downloadTaskWithRequest:request];
// 同NSURLConnection同樣,有代理方法也就有block方法
// [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
// }];
}
#pragma mark 點擊下載
- (void)didClickDownloadButtonAction:(UIButton *)button{
// 由於任務默認是掛起狀態,須要恢復任務(執行任務)
[_sessionDownloadTask resume];
}
#pragma mark 點擊上傳
- (void)didClickUploadButtonAction:(UIButton *)button{
//判斷imageView是否有內容
if (_imageView.image == nil) {
NSLog(@"image view is empty");
return;
}
// 0. 上傳以前在界面上添加指示符
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
// 設置位置???
CGSize size = _imageView.bounds.size;
indicator.center = CGPointMake(size.width / 2.0, size.height / 2.0);
[self.imageView addSubview:indicator];
[indicator startAnimating];
// 1. URL
NSURL *url = [NSURL URLWithString:@"http://www.bizhiwa.com/uploads/allimg/2012-01/22021207-1-311536.jpg"];
// 2. Request -> PUT,request的默認操做是GET
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:5.0f];
request.HTTPMethod = @"PUT";
// *** 設置網絡請求的身份驗證! ***
// 1> 受權字符串
NSString *authStr = @"admin:123456";
// 2> BASE64的編碼,避免數據在網絡上以明文傳輸
// iOS中,僅對NSData類型的數據提供了BASE64的編碼支持
NSData *authData = [authStr dataUsingEncoding:NSUTF8StringEncoding];
NSString *encodeStr = [authData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn];
NSString *authValue = [NSString stringWithFormat:@"Basic %@", encodeStr];
[request setValue:authValue forHTTPHeaderField:@"Authorization"];
// 3. Session
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]];
// 4. UploadTask
NSData *imageData = UIImageJPEGRepresentation(_imageView.image, 0.75);
// 應用block的請求方式
NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:imageData completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
// 上傳完成後,data參數轉換成string就是服務器返回的內容
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"OK -> %@", str);
[NSThread sleepForTimeInterval:5.0f];
dispatch_async(dispatch_get_main_queue(), ^{
[indicator stopAnimating];
[indicator removeFromSuperview];
});
}];
// 由於任務默認是掛起狀態,須要恢復任務(執行任務)
[uploadTask resume];
}
#pragma mark 點擊取消
// NSURLConnection一旦發送是無法取消的。可是,咱們能夠很容易的取消掉一個NSURLSessionTask任務
- (void)didClickCancleButtonAction:(UIButton *)button{
/**
* 當取消後,會回調這個URLSession:task:didCompleteWithError:代理方法,通知你去及時更新UI。當取消一個任務後,也
* 十分可能會再一次回調這個代理方法URLSession:downloadTask:didWriteData:BytesWritten:totalBytesExpectedToWrite:
* 固然,didComplete 方法確定是最後一個回調的。
*/
// if (_sessionDownloadTask) {
//
// // 取消下載請求
// [_sessionDownloadTask cancel];
// _sessionDownloadTask = nil;
// }
if (!self.sessionDownloadTask) {
// 中止下載任務,把待恢復的數據保存到一個變量中,方便後面恢復下載使用
[self.sessionDownloadTask cancelByProducingResumeData:^(NSData *resumeData) {
self.partialData = resumeData;
self.sessionDownloadTask = nil;
}];
}
}
#pragma mark 恢復下載(斷點續傳)
- (void)didClickResuableButtonAction:(UIButton *)button{
if (self.partialData) {
self.sessionDownloadTask = [self.urlSession downloadTaskWithResumeData:self.partialData];
self.partialData = nil;
}else{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://pic4.duowan.com/wow/1002/130782267821/130782458426.jpg"]];
self.resumableTask = [self.urlSession downloadTaskWithRequest:request];
}
[self.sessionDownloadTask resume];
}
#pragma mark 後臺下載模式
- (void)didClickBackgroundButtonAction:(UIButton *)button{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://dldir1.qq.com/qqfile/QQforMac/QQ_V3.1.2.dmg"]];
self.backgroundTask = [[self backgroundSession] downloadTaskWithRequest:request];
[self.backgroundTask resume];
}
#pragma mark - NSURLSessionDownloadTaskDelegate
// 下載完成
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{
/**
*******->appDelegete裏面的方法
typedef void(^MyBlock)();
@property (copy, nonatomic) MyBlock backgroundURLSessionCompletionHandler;
*/
// 後臺請求結束時調用的方法
// - (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler{
//
// self.backgroundURLSessionCompletionHandler = completionHandler;
// }
// // 若是是後臺NSURLSession,後臺請求結束後會調用這個方法,通知你應該更新UI了
// if (session == [self backgroundSession]) {
//
// self.backgroundTask = nil;
// AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
// if (appDelegate.backgroundURLSessionCompletionHandler) {
//
// void(^handler)() = appDelegate.backgroundURLSessionCompletionHandler;
// appDelegate.backgroundURLSessionCompletionHandler = nil;
// handler();
// }
//
// }
// 這裏的緩存處理作的很差,你們按本身的方法處理就行,還有圖片的存儲以它自己的URL路徑爲準,這樣是不會有重複的
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *cachesURLPath = [[fileManager URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] lastObject];
// 根據URL獲取到下載的文件名,拼接成沙盒的存儲路徑(location是下載的臨時文件目錄,在tmp文件夾裏面)
NSURL *destinationPath = [cachesURLPath URLByAppendingPathComponent:[location lastPathComponent]];
NSError *error = nil;
BOOL success = [fileManager moveItemAtURL:location toURL:destinationPath error:&error];
[fileManager removeItemAtURL:location error:NULL];
// location是下載的臨時文件目錄,將文件從臨時文件夾複製到沙盒
// BOOL success = [fileManager copyItemAtURL:location toURL:destinationPath error:&error];
if (success) {
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *image = [UIImage imageWithContentsOfFile:[destinationPath path]];
self.imageView.image = image;
// UIImageView會自動裁剪圖片適應它的frame,下面這個屬性就是展現原圖
self.imageView.contentMode = UIViewContentModeScaleAspectFill;
});
}
}
// 無論任務是否成功,在完成後都會回調這個代理方法
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
// 若是error是nil,則證實下載是成功的,不然就要經過它來查詢失敗的緣由。若是下載了一部分,這個error會包含一個NSData對象,若是後面要恢復任務能夠用到
if (error == nil) {
dispatch_async(dispatch_get_main_queue(), ^{
self.progressIndicator.hidden = YES;
});
}
}
// 傳輸進度
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
double currentValue = totalBytesWritten / (double)totalBytesExpectedToWrite;
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"%f",currentValue);
self.progressIndicator.hidden = NO;
self.progressIndicator.progress = currentValue;
});
}
// 未知
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes{
}
#pragma mark - NSURLSession另外一個重要的特性:即便當應用不在前臺時,你也能夠繼續傳輸任務。固然,咱們的會話模式也要爲後臺模式
- (NSURLSession *)backgroundSession{
// 經過給的後臺token,咱們只能建立一個後臺會話,因此這裏使用dispatch once block
static NSURLSession *backgroundSession = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSURLSessionConfiguration *config = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.shinobicontrols.BackgroundDownload.BackgroundSession"];
backgroundSession = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
});
return backgroundSession;
}
@end