<1> NSURLSession 簡介:
{
NSURLSession 是 iOS 7.0 以後推出的網絡解決方案!用於替代 NSURLConnection, 針對下載/上傳等複雜的網絡操做提供了專門的解決方案!
NSURLSession 使用更加簡單/方便!
}
<2> NSURLSession 中新增的內容:
{
1> 全局的 NSURLSession 對象: 全部的網絡會話都由一個 NSURLSession 對象發起, 實例化一個 NSURLSession 對象有兩種方法:
{
*1 對於簡單的,不須要監聽網絡請求過程的網絡會話來講,使用系統提供的,全局的 NSURLSession 單利對象:
NSURLSession *session = [NSURLSession sharedSession];
*2 若是須要監聽網絡進度,須要自定義一個 NSURLSession 對象,而且設置代理!這時還須要一個 NSURLSessionConfiguration,能夠設置全局的網絡訪問屬性.
NSURLSessionConfiguration *cfg = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:cfg delegate:self delegateQueue:[NSOperationQueue mainQueue]];
}
2> 網絡任務(Task);在 NSURLSession 中,有三種網絡任務類型.
{
*1 用於非文件下載的普通的 GET/POST請求 NSURLSessionDataTask.實例化對象有如下2種方法:
{
// 1> 經過一個 request 實例化普通網絡任務,增長完成以後的 block 回調,使用比較多.
NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
}];
// 2> 經過一個 url 實例化普通網絡任務,增長完成以後的 block 回調,使用比較多.
NSURLSessionDataTask *task = [self.session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
}];
}
*2 用於文件下載的網絡任務 NSURLSessionDownloadTask (不管文件大小,下載都使用 NSURLSessionDownloadTask) ,實例化對象有如下三種方法:
{
// 1> 經過一個 request 實例化下載網絡任務,增長任務完成以後的 block 回調,通常用在小文件下載.
NSURLSessionDownloadTask *task = [self.session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
}];
// 2> 經過一個 url 實例化下載網絡任務,增長任務完成以後的 block 回調,通常用在小文件下載.
NSURLSessionDownloadTask *task = [self.session downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
}];
// 3> 經過以前下載的數據 ResumeData ,實例化一個下載任務,用於斷點續傳.
NSURLSessionDownloadTask *task = [session downloadTaskWithResumeData:ResumeData completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
}];
}
*3 用於文件上傳的網絡任務 NSURLSessionUploadTask.
{
// 目前,只有經過這種方式實例化的下載任務,才能實現文件上傳.依然須要拼接數據.
NSURLSessionUploadTask *task = [session uploadTaskWithRequest:request fromData:fromData completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
//
}]
}
}
}
<3> NSURLSession 的使用分爲三步:
{
1> 實例化一個 NSURLSession 對象 session ;
NSURLSession *session = [NSURLSession sharedSession];
2> 經過 NSURLSession 對象,實例化對應的網絡任務 task;
NSURLSessionDataTask *task = [session dataTaskWithRequest:request];
3> 開啓網絡任務
[task resume];
}
}
/*------------------------------------ 02 NSURLSession 下載的斷點續傳 ---------------------------*/
1.使用 NSURLSession 實現下載任務. php
2.實時監聽下載進度,使用斷點續傳.
{
利用 NSURLSession 實現文件下載,首先須要建立一個 NSURLSessionDownloadTask; 因爲須要實時監聽下載進度,因此,須要實現 <NSURLSessionDownloadDelegate>方法,這樣,就須要自定義一個會話 session.而且制定代理.
// NSURLSession 下載的斷點續傳實現步驟:
1. 懶加載全局網絡會話
{
-(NSURLSession *)session
{
if (!_session) {
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
_session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
}
return _session;
}
}
2. 利用全局網絡會話,建立下載 task, 開始下載任務
{
self.task = [self.session downloadTaskWithURL:url];
[self.task resume];
}
3. 在代理方法中,實時監聽下載進度
{
// 監聽下載進度的方法
// bytesWritten :本次下載的字節數
// totalBytesWritten :已經下載的字節數
// totalBytesExpectedToWrite :下載文件的總字節數
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
NSLog(@"代理回調~");
float progress = (float)totalBytesWritten/totalBytesExpectedToWrite;
dispatch_async(dispatch_get_main_queue(), ^{
self.progress.progress = progress;
});
}
// 完成下載的時候調用
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
NSLog(@"下載完成%@",location);
}
// 斷點續傳的代理方法,暫時什麼都不寫
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
NSLog(@"%s",__FUNCTION__);
}
}
4. 當點擊暫停以後,應該取消下載任務,記錄當前下載的文件數據,而且將 task 任務設爲 nil
{
[self.task cancelByProducingResumeData:^(NSData *resumeData) {
self.reusemData = resumeData;
self.task = nil;
}];
}
5. 當點擊繼續以後,應該從上次下載的進度繼續下載,這時,從新建立下載 task, 而且是根據上次記錄的文件下載數據來實例化下載任務
{
if (!self.reusemData) {
return;
}
self.task = [self.session downloadTaskWithResumeData:self.reusemData];
self.reusemData = nil;
[self.task resume];
}
}
/*------------------------------------- 03 NSURLSession 實現上傳文件 -----------------------------*/
1.使用 NSURLSession 實現文件上傳.
{
NSURLSession 上傳文件和 NSURLConnection 同樣須要按格式拼接文件數據.重要的是要學會封裝方法,具體使用以下:
{
// NSURLSession 作文件上傳
- (void)uploadMfileSession
{
// 1.實例化全局網絡會話
NSURLSession *session = [NSURLSession sharedSession];
// 2.建立網絡請求
{
NSURL *url = [NSURL URLWithString:@"http://localhost/upload/upload-m.php"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// 設置請求方法
request.HTTPMethod = @"POST";
// 告訴服務器,須要作文件上傳
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",kBOUNDARY];
[request setValue:contentType forHTTPHeaderField:@"Content-Type"];
}
// 3. 將須要上傳至服務器的文件包裝在字典中.
{
// 須要上傳的文件路徑
NSString *file1 = @"/Users/likaining/Desktop/meinv.jpg";
NSString *file2 = @"/Users/likaining/Downloads/XMLdemo.xml";
// 文件在服務器中保存的名稱
NSString *fileName1 = @"meinv";
NSString *fileName2 = @"demo";
// 將上傳數據包裝在字典中
NSMutableDictionary *fileDict = [NSMutableDictionary dictionary];
[fileDict setObject:file1 forKey:fileName1];
[fileDict setObject:file2 forKey:fileName2];
}
// 4. 將須要上傳的非文件數據也包裝在字典中
{
NSMutableDictionary *parameter = [NSMutableDictionary dictionary];
[parameter setObject:@"likaining" forKey:@"username"];
}
// 5. 將須要上傳的數據,按照上傳的數據格式化數據.而且轉爲二進制數據.
NSData *dataM = [self formDataWithfileName:@"userfile[]" fileDict:fileDict parameter:parameter];
// 6. 利用網絡會話,創建上傳任務
NSURLSessionUploadTask *task = [session uploadTaskWithRequest:request fromData:dataM completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
//
NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
NSLog(@"response: %@",response);
}];
// 7 .開始上傳.
[task resume];
}
// 格式化上傳數據的方法封裝.
- (NSData *) formDataWithfileName:(NSString *)fileName fileDict:(NSDictionary *)fileDict parameter:(NSDictionary *)parameter
{
NSMutableData *data = [NSMutableData data];
// key : 服務器保存的文件名
// obj : 上傳的文件地址
[fileDict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
//
NSMutableString *headerStrM = [NSMutableString stringWithFormat:@"\r\n--%@\r\n",kBOUNDARY];
[headerStrM appendFormat:@"Content-Disposition: form-data; name=%@; filename=%@\r\n",fileName,key];
NSString *contentType = [self getContentTypeFromFile:obj];
[headerStrM appendFormat:@"Content-Type: %@\r\n\r\n",contentType];
NSData *headerData = [headerStrM dataUsingEncoding:NSUTF8StringEncoding];
NSData *fileData = [NSData dataWithContentsOfFile:obj];
[data appendData:headerData];
[data appendData:fileData];
}];
// key :username 服務器接收的 key
// obj :上傳文件的人
[parameter enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
//
NSMutableString *headerM = [NSMutableString stringWithFormat:@"\r\n--%@\r\n",kBOUNDARY];
[headerM appendFormat:@"Content-Disposition: form-data; name=%@\r\n\r\n",key];
NSString *username = obj;
NSData *headerData = [headerM dataUsingEncoding:NSUTF8StringEncoding];
NSData *userData = [username dataUsingEncoding:NSUTF8StringEncoding];
[data appendData:headerData];
[data appendData:userData];
}];
NSMutableString *footerStrM = [NSMutableString stringWithFormat:@"\r\n--%@--\r\n",kBOUNDARY];
NSData *footerData = [footerStrM dataUsingEncoding:NSUTF8StringEncoding];
[data appendData:footerData];
return data;
}
}
}
/*------------------------------------- 04 文件的複製和剪切 ---------------------------------------*/
文件操做中的複製和剪切.
{
文件下載到本地以後,有時候須要對文件進行移動操做,這樣就須要掌握掌握文件的複製和剪切操做.
1.文件的拷貝
// 新建一個文件路徑
NSString *path = @"/Users/likaining/Desktop/abc/";
// 從一個文件路徑拷貝文件到另外一個文件路徑
// AtPath : 拷貝前的文件路徑
// ToPath : 拷貝後的文件路徑
[[NSFileManager defaultManager] copyItemAtPath:location.path toPath:path error:0];
2.文件的剪切
// response.suggestedFilename:建議使用的文件名,通常跟服務器端的文件名一致
NSString *file = [caches stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
// 將臨時文件剪切到Caches文件夾
// AtPath : 剪切前的文件路徑
// ToPath : 剪切後的文件路徑
[[NSFileManager defaultManager] moveItemAtPath:location.path toPath:file error:nil];
}
/*------------------------------------- 05 文件的解壓縮 ------------------------------------------*/
文件的解壓縮操做,使用解壓縮框架.
{
爲了方便網絡傳輸,文件常常被壓縮以後再進行網絡傳輸,這個時候,須要學會解壓縮文件.
1.文件的解壓縮須要導入第三方框架: SSZipArchive ,須要注意的是,這個框架依賴一個動態度 libz.dylib.
2. 壓縮文件:
// 1.得到須要壓縮的文件夾
NSString *images = [caches stringByAppendingPathComponent:@"images"];
// 1.建立一個zip文件(壓縮)
NSString *zipFile = [caches stringByAppendingPathComponent:@"images.zip"];
BOOL result = [SSZipArchive createZipFileAtPath:zipFile withContentsOfDirectory:images];
3. 解壓縮文件:
// location.path:須要解壓縮的文件
// 文件解壓縮以後存放的路徑(注意,只須要給出一個文件路徑就能夠,由於極可能解壓縮以後,生成不少個文件).
[SSZipArchive unzipFileAtPath:location.path toDestination:path];
}
web