使用NSURLSession
進(jìn)行上傳和下載任務(wù),NSURLSession
是iOS7之后推出的,具有downLoadTask
和upLoadTask
功能沙合,實(shí)現(xiàn)任務(wù)時(shí),會(huì)先將任務(wù)掛起,這樣可以實(shí)現(xiàn)斷點(diǎn)續(xù)傳功能刀荒,使用時(shí)候要注意resume
下載
- 最簡(jiǎn)單的下載
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 1. URL
NSString *urlString = @"http://192.168.26.201/0805空缺數(shù)據(jù) 2.xls.zip";
// 添加 % 轉(zhuǎn)義
urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:urlString];
// NSURLSession,sharedSession是一個(gè)全局共享的單例,蘋果為了方便程序員使用簡(jiǎn)單的網(wǎng)絡(luò)任務(wù)
// NSURLSession *session = [NSURLSession sharedSession];
// 2. 由sharedSession發(fā)起網(wǎng)絡(luò)會(huì)話任務(wù)
[[[NSURLSession sharedSession] downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
NSLog(@"%@", [NSBundle mainBundle].bundlePath);
NSLog(@"%@", location);
}] resume];
}
- 下載解壓縮
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSString *urlString = @"http://192.168.26.201/0805空缺數(shù)據(jù) 2.xls.zip";
// 添加 % 轉(zhuǎn)義
urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:urlString];
// NSURLSession,sharedSession是一個(gè)全局共享的單例,蘋果為了方便程序員使用簡(jiǎn)單的網(wǎng)絡(luò)任務(wù)
NSURLSession *session = [NSURLSession sharedSession];
// 由session發(fā)起下載任務(wù),在URLSession中,所有的任務(wù)都是由session發(fā)起的
// 下載任務(wù)會(huì)保存在tmp文件夾中,如果沒(méi)有處理,下載的文件會(huì)被刪除!
/**
從網(wǎng)絡(luò)上下載小說(shuō)
1. 下載這個(gè)小說(shuō)的zip
2. 下載完成之后,可以解壓縮,原有的zip包就不需要了
3. URLSession會(huì)自動(dòng)幫我們刪除這個(gè)zip包
但是如果調(diào)用了這個(gè)方法不會(huì)調(diào)用相應(yīng)的代理方法,原因不詳,望賜教
*/
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
NSLog(@"%@", [NSBundle mainBundle].bundlePath);
NSLog(@"%@", location);
// 將下載的文件解壓縮到cache目錄 - 重新啟動(dòng)不會(huì)刪除
NSString *cacheDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
// 解壓縮 path屬性可以拿到URL中對(duì)應(yīng)的路徑
//使用了解壓縮框架ZipArchive
[SSZipArchive unzipFileAtPath:location.path toDestination:cacheDir];
}];
// 所有的任務(wù),默認(rèn)都是掛起的,需要resume
[task resume];
}
- 三個(gè)代理方法
pragma mark - NSURLSession下載代理方法
1.下載完成
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
//這個(gè)操作本身是在異步線程中完成的,如果想要在這個(gè)線程中完成下載解壓操作棘钞,需要在異步線程完成照棋。但是更新UI的操作如collectionView的reloadData要放到主線程去進(jìn)行
//如果要在這個(gè)方法中使用下載解壓操作,要放到
NSLog(@"下載完成 %@", location);
}
2.斷點(diǎn)續(xù)傳使用
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
// 什么也不寫
}
3.下載進(jìn)度
/**
bytesWritten 本次下載的字節(jié)數(shù)
totalBytesWritten 已經(jīng)下載的字節(jié)數(shù)
totalBytesExpectedToWrite 下載文件總字節(jié)數(shù)
*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
// 進(jìn)度 = 已經(jīng)下載 / 總大小
float progress = (float)totalBytesWritten / totalBytesExpectedToWrite;
NSLog(@"%f %@", progress, [NSThread currentThread]);
// 主線程更新UI GCD
// dispatch_async(dispatch_get_main_queue(), ^ { self.progressView.progress = progress;});
// NSOperation
[[NSOperationQueue mainQueue] addOperationWithBlock: ^ {
//進(jìn)度條
self.pView.progress = progress;
}];
}
- 斷點(diǎn)續(xù)傳
主要的是關(guān)于任務(wù)開(kāi)始和釋放
(注意)
使用下面這個(gè)辦法注冊(cè)NSURLSession
對(duì)象時(shí),需要注意到隊(duì)列,可以使用主隊(duì)列,這樣下載任務(wù)只在主隊(duì)列進(jìn)行,使用自己定義的隊(duì)列或者使用nil
的時(shí)候,為異步并發(fā)隊(duì)列
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(id <NSURLSessionDelegate>)delegate delegateQueue:(NSOperationQueue *)queue;
- (NSURLSession *)session
{
if (_session == nil) {
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
_session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
}
return _session;
}
// 開(kāi)始
- (IBAction)start
{
self.pView.progress = 0.0f;
// 1. URL
NSString *urlString = @"http://192.168.26.201/2014蘋果發(fā)布者大會(huì).mp4";
urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:urlString];
// 2. session
// NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
// NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
// 3. 下載任務(wù)
self.downloadTask = [self.session downloadTaskWithURL:url];
[self.downloadTask resume];
}
// 暫停
- (IBAction)pause
{
// 如果已經(jīng)暫停,應(yīng)該不能再一次暫停
NSLog(@"%s", __func__);
[self.downloadTask cancelByProducingResumeData:^(NSData *resumeData) {
NSLog(@"====> %zd", resumeData.length);
// 需要把resumeData保存下來(lái),才能保證后續(xù)的續(xù)傳能夠執(zhí)行
self.resumeData = resumeData;
// 釋放下載任務(wù)!
self.downloadTask = nil;
}];
}
// 繼續(xù)
- (IBAction)resume
{
// 如果已經(jīng)繼續(xù),應(yīng)該不能再次繼續(xù)
if (self.resumeData == nil) {
// 說(shuō)明前一次沒(méi)有被暫停的下載任務(wù)
return;
}
// 發(fā)起續(xù)傳的網(wǎng)絡(luò)下載任務(wù)
// [[self.session downloadTaskWithResumeData:self.resumeData] resume];
self.downloadTask = [self.session downloadTaskWithResumeData:self.resumeData];
// 釋放resumeData
self.resumeData = nil;
[self.downloadTask resume];
}
- PUT上傳武翎、刪除文件
@implementation CZViewController
/**
PUT 方法可以上傳任意大小的文件
// 設(shè)置HTTP請(qǐng)求頭屬性
// ****** 注意:不同的網(wǎng)絡(luò)環(huán)境變化,通常都是設(shè)置HTTP的請(qǐng)求頭字段,通過(guò)請(qǐng)求頭字段可以告訴服務(wù)器很多內(nèi)容!
// 譬如:上傳文件,授權(quán)信息等等,具體如何設(shè)置,公司的后端程序員會(huì)告訴前端
1. 需要身份驗(yàn)證
NSString *authStr = @"admin:123456";
NSString *authBase64 = [@"BASIC " stringByAppendingString:[self base64:authStr]];
[request setValue:authBase64 forHTTPHeaderField:@"Authorization"];
* DELETE 刪除服務(wù)器上的文件
request.HTTPMethod = @"DELETE";
身份驗(yàn)證和PUT一致!
*/
// PUT上傳
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self putUpload];
}
/** 刪除服務(wù)器上的文件 Web-DAV */
- (void)deleteFile
{
// 1. URL 中需要指定PUT上傳到服務(wù)器上的文件名
NSURL *url = [NSURL URLWithString:@"http://192.168.26.201/uploads/123.mp4"];
// 2. request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"DELETE";
// 2.1 設(shè)置用戶名和密碼
NSString *authStr = @"admin:123456";
// 結(jié)果: "BASIC YWRtaW46MTIzNDU2"
NSString *authBase64 = [@"BASIC " stringByAppendingString:[self base64:authStr]];
// 設(shè)置HTTP請(qǐng)求頭屬性
// ****** 注意:不同的網(wǎng)絡(luò)環(huán)境變化,通常都是設(shè)置HTTP的請(qǐng)求頭字段,通過(guò)請(qǐng)求頭字段可以告訴服務(wù)器很多內(nèi)容!
// 譬如:上傳文件,授權(quán)信息等等,具體如何設(shè)置,公司的后端程序員會(huì)告訴前端
[request setValue:authBase64 forHTTPHeaderField:@"Authorization"];
// 3. sesssion 只能使用request進(jìn)行DELETE刪除
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(@"完成!");
}] resume];
}
- (void)putUpload
{
// 1. URL 中需要指定PUT上傳到服務(wù)器上的文件名
NSURL *url = [NSURL URLWithString:@"http://192.168.26.201/uploads/123.png"];
// 2. request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"PUT";
// 2.1 設(shè)置用戶名和密碼
NSString *authStr = @"admin:123456";
// 結(jié)果: "BASIC YWRtaW46MTIzNDU2"
NSString *authBase64 = [@"BASIC " stringByAppendingString:[self base64:authStr]];
// 設(shè)置HTTP請(qǐng)求頭屬性
// ****** 注意:不同的網(wǎng)絡(luò)環(huán)境變化,通常都是設(shè)置HTTP的請(qǐng)求頭字段,通過(guò)請(qǐng)求頭字段可以告訴服務(wù)器很多內(nèi)容!
// 譬如:上傳文件,授權(quán)信息等等,具體如何設(shè)置,公司的后端程序員會(huì)告訴前端
[request setValue:authBase64 forHTTPHeaderField:@"Authorization"];
// 3. sesssion 只能使用request進(jìn)行PUT上傳
// 參數(shù)fromFile -> 本地要上傳文件的完成URL
NSURL *localURL = [[NSBundle mainBundle] URLForResource:@"02.網(wǎng)絡(luò)應(yīng)用層次結(jié)構(gòu).mp4" withExtension:nil];
// 4. 跟蹤上傳進(jìn)度
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
[[session uploadTaskWithRequest:request fromFile:localURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
// 提示,跟蹤的時(shí)候一定不要只輸出result
// 提示:如果是覆蓋文件,NSData沒(méi)有內(nèi)容
NSLog(@"====> %@", result);
}] resume];
}
#pragma mark - 上傳文件進(jìn)度代理方法
/**
bytesSent 本次上傳字節(jié)數(shù)
totalBytesSent 總共上傳字節(jié)數(shù)
totalBytesExpectedToSend 要上傳的字節(jié)數(shù)
*/
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
float progress = (float)totalBytesSent / totalBytesExpectedToSend;
NSLog(@"%f %@", progress, [NSThread currentThread]);
}
/**
將指定的字符串,進(jìn)行base64編碼
BASE64 - 是網(wǎng)絡(luò)上最常用的編碼方式之一(可以編碼->看不懂,可以解碼->又看的懂了)
BASE64是很多加密算法中的基礎(chǔ)算法!
能夠達(dá)到的效果,將二進(jìn)制文件轉(zhuǎn)換成ASCII碼,從而可以將二進(jìn)制文件的結(jié)果直接當(dāng)成URL的參數(shù)傳遞
*/
- (NSString *)base64:(NSString *)string
{
// 1. 將字符串轉(zhuǎn)換成二進(jìn)制數(shù)據(jù)
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
// 2. 進(jìn)行base64編碼
return [data base64EncodedStringWithOptions:0];
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"%@", [self base64:@"admin:123456"]);
}
- post上傳
用到分類
鏈接: http://pan.baidu.com/s/1mgCKndm 密碼: ghq4
POST 上傳
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 1. URL,是真正負(fù)責(zé)上傳的腳本(php)文件
NSURL *url = [NSURL URLWithString:@"http://localhost/post/upload.php"];
// 2. request
/**
1> 負(fù)責(zé)上傳文件的URL
2> 上傳的文件名:保存在服務(wù)器上的文件名稱
3> 本地要上傳文件的完整路徑
*/
NSString *localPath = [[NSBundle mainBundle] pathForResource:@"001.png" ofType:nil];
NSURLRequest *request = [NSMutableURLRequest requestWithUploadURL:url uploadFileName:@"123.png" localFilePath:localPath];
// 3. 上傳
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}] resume];
}