NSURLSession 概述
- NSURLSession iOS 7.0 發(fā)布
- 可以暫停犁嗅、停止褂微、重啟網(wǎng)絡(luò)任務(wù)
- 請求可以使用一樣的 配置容器
- 除了 下載,block 和代理可以同時起作用
- 為了方便使用霞赫,蘋果提供了一個全局的 session
- 所有的 task 都需要 session 發(fā)起
- 所有的 task 默認都是 掛起 的端衰,需要 resume
- NSURLSession 支持后臺操作甘改,除非用戶強制關(guān)閉
NSURLSession 的 Task
- NSURLSessionDataTask
上傳下載都可以十艾,適合小數(shù)據(jù) - NSURLSessionUploadTask
上傳用的 Task - NSURLSessionDownloadTask
下載用的 Task
NSURLSessionDataTask
- 適合小數(shù)據(jù)(JSON or Plist or HTML or XML or 小圖像)
P.S.(Postscript)
其實對于小數(shù)據(jù),NSURLConnection 也是同樣適合的
GET 請求
NSURL *url = [NSURL URLWithString:@"http://127.0.0.1/login.php?username=username&password=pwd"];
// data 或者 request 都是可以的
NSURLSessionDataTask *taskGET = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error == nil && data.length > 0) {
NSLog(@"data -- %@", data);
} else {
NSLog(@"error -- %@", error);
NSLog(@"response -- %@", response);
}
}];
[taskGET resume];
POST 請求
NSURL *url = [NSURL URLWithString:@"http://127.0.0.1/login.php"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
NSData *requestBody = [@"username=username&password=pwd" dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPBody = requestBody;
NSURLSessionDataTask *taskPOST = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error == nil && data.length > 0) {
NSLog(@"data -- %@", data);
id result = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
NSLog(@"result -- %@", result);
} else {
NSLog(@"error -- %@", error);
NSLog(@"response -- %@", response);
}
}];
[taskPOST resume];
NSURLSessionUploadTask
POST 請求
#define kBoundary @"suxiaonao"
- (void)testSessionUploadTask {
// create URL
NSURL *url = [NSURL URLWithString:@"http://127.0.0.1/post/upload.php"];
// create POST request
// 上傳一般不會用到 GET 請求
// 首先,字面理解 POST 就更合適一些
// 其次康吵,GET 請求會把請求體拼接在 URL 后面晦嵌,雖然 HTTP 沒有限制 URL 的長度,但是旱函,服務(wù)器和瀏覽器會有限制
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// request method
request.HTTPMethod = @"POST";
// request head setValue: forHTTPHeaderField:
// 這兒需要設(shè)置一下 HTTPHeaderField棒妨,感覺是和 kBoundary 有關(guān)含长,因為后面拼接請求體的時候也是需要用到 kBoundary 的,如果我們在這兒給某個 HTTPHeaderField 賦值了颅眶,就會替換掉默認值,并且需要注意大小寫敏感
[request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", kBoundary] forHTTPHeaderField:@"Content-Type"];
// request body
// connection 是把上傳數(shù)據(jù)放在請求體里面偷厦,session 會把上傳數(shù)據(jù)放在 uploadTaskWithRequest: 這個方法的第二個參數(shù)里面
// session send upload
// dataWithFieldName: 就是在做請求體拼接
NSURLSessionUploadTask *uploadTask = [[NSURLSession sharedSession] uploadTaskWithRequest:request fromData:[self dataWithFieldName:@"userfile" fileName:@"cba.txt" fileContent:[NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"abc.txt" ofType:nil] encoding:NSUTF8StringEncoding error:NULL]] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error == nil && data.length > 0) {
id result = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
NSLog(@"result -- %@", result);
} else {
NSLog(@"error -- %@", error);
}
}];
[uploadTask resume];
}
dataWithFieldName: fileName: fileContent: 方法實現(xiàn)
//-----------------------------1499715155697045246716155137
//Content-Disposition: form-data; name="userfile"; filename="abc.txt"
//Content-Type: text/plain
//
//Hello!!
//-----------------------------1499715155697045246716155137--
- (NSData *)dataWithFieldName:(NSString *)fieldName fileName:(NSString *)fileName fileContent:(NSString *)fileContent {
NSMutableString *stringM = [NSMutableString string];
[stringM appendFormat:@"--%@\r\n", kBoundary];
[stringM appendFormat:@"Content-Disposition: form-data; name=%@; filename=%@\r\n", fieldName, fileName];
// Content-Type 有很多只泼,如果不確定卵洗,寫 application/octet-strea 就好
// [stringM appendString:@"Content-Type: text/plain\r\n\r\n"];
// [stringM appendString:@"Content-Type: image/png\r\n\r\n"];
[stringM appendString:@"Content-Type: application/octet-strea\r\n\r\n"];
[stringM appendFormat:@"%@\r\n", fileContent];
[stringM appendFormat:@"--%@--\r\n\r\n", kBoundary];
NSData *data = [stringM.copy dataUsingEncoding:NSUTF8StringEncoding];
return data;
}
NSURLSessionDownloadTask
- 說到下載过蹂,需要引入一個概念 —— NSURLSessionConfiguration(工作模式)
- DataTask 和 UploadTask 都在用系統(tǒng)提供的 session,所以沒有設(shè)置過 configuration
- NSURLSessionConfiguration 有三種模式
- defaultSessionConfiguration
默認模式本橙,和 NSURLConnection 類似脆诉,使用全局單例击胜,通過 Cache 和 Cookie 存儲對象 - ephemeralSessionConfiguration
及時模式,不能持續(xù)使用 Cache 和 Cookie 存儲對象 - backgroundSessionConfiguration
后臺模式骚揍,可以在后臺完成上傳下載,創(chuàng)建 configuration 的時候嘲叔,需要有一個 identifier硫戈,用于 session 在后臺工作的時候下硕,確定是哪一個 session 完成的
- defaultSessionConfiguration
- 下載一般會去自定義 session,同時設(shè)置代理梭姓,并且如果設(shè)置了代理霜幼,block 就不會再起作用
- NSURLSessionDownloadTask 會把下載的文件放到 tmp 文件夾里面,記得自己去做存儲
NSURL *url = [NSURL URLWithString:@"http://127.0.0.1/files.zip"];
// 這兒用的是 defaultSessionConfiguration
NSURLSession *downloadSession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
NSURLSessionDownloadTask *downloadTask = [downloadSession downloadTaskWithURL:url];
[downloadTask resume];
// 然后根據(jù)需要實現(xiàn)代理方法就好
NSURLSession 和 NSURLConnection 下載比較
- NSURLSession 下載的時候可以暫停誉尖、繼續(xù)罪既,但是,NSURLConnection 不可以
- NSURLSession 和 NSURLConnection 都可以取消铡恕,一旦取消琢感,下次就要重新發(fā)布或者連接
- NSURLSession 和 NSURLConnection 下載都可以指定 range,修改請求頭就好