iOS-NSURLSession上傳文件

NSURLConnection在iOS 9被棄用,NSURLSession是iOS7中新增接口,
NSURLSession,與NSURLConnection是并列的,且可以支持后臺(tái)相關(guān)的網(wǎng)絡(luò)操作的新特性,NSURLSession把NSURLConnection替換成NSURLSession, NSURLSessionConfiguration,NSURLSessionTask.

基礎(chǔ)知識(shí)

NSURLSessionTask是一個(gè)抽象類,直接使用的三個(gè)子類NSURLSessionDataTask,NSURLSessionUploadTask和NSURLSessionDownloadTask.NSURLSessionDataTask可以執(zhí)行后面兩個(gè)子類的功能.
NSURLSessionDataTask-Get方法:


    NSURL *url = [NSURL URLWithString:@"http://www.lxweimin.com/u/24da48b2ddb3"];

    NSMutableURLRequest *request =[NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = @"GET";

    NSURLSession *session = [NSURLSession sharedSession];
 
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        NSLog(@"獲取到數(shù)據(jù)");
    }];
    // 執(zhí)行任務(wù)/繼續(xù)執(zhí)行
    [dataTask resume];
    //[dataTask suspend];//暫停

NSURLSessionDataTask-Post方法:

    NSURL *url = [NSURL URLWithString:@"http://www.lxweimin.com/u/24da48b2ddb3"];
    
    NSMutableURLRequest *request =[NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = @"POST";
    
    NSString *params = @"userName=FlyElephant";//post參數(shù)
    request.HTTPBody = [params dataUsingEncoding:NSUTF8StringEncoding];
    
    NSURLSession *session = [NSURLSession sharedSession];
    
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        NSLog(@"獲取到數(shù)據(jù)");
    }];
    // 執(zhí)行任務(wù)/繼續(xù)執(zhí)行
    [dataTask resume];
    //[dataTask suspend];//暫停```
NSURLSessionDownloadTask-下載文件:
   NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
                                                          delegate:self
                                                     delegateQueue:[[NSOperationQueue alloc] init]];
    
    NSURL *url = [NSURL URLWithString:@"http://www.lxweimin.com/u/24da48b2ddb3"];
    
    NSMutableURLRequest *request =[NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = @"GET";
    
    NSURLSessionDownloadTask *dataTask = [session downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        NSLog(@"FlyElephant-下載成功");
    }];
    // 執(zhí)行任務(wù)/繼續(xù)執(zhí)行
    [dataTask resume];

第三種方式可以設(shè)置delegate,NSURLSessionDelegate定義如下:

@protocol NSURLSessionDelegate <NSObject>
@optional

/* The last message a session receives.  A session will only become
 * invalid because of a systemic error or when it has been
 * explicitly invalidated, in which case the error parameter will be nil.
 */
- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(nullable NSError *)error;

/* If implemented, when a connection level authentication challenge
 * has occurred, this delegate will be given the opportunity to
 * provide authentication credentials to the underlying
 * connection. Some types of authentication will apply to more than
 * one request on a given connection to a server (SSL Server Trust
 * challenges).  If this delegate message is not implemented, the 
 * behavior will be to use the default handling, which may involve user
 * interaction. 
 */
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
                                             completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler;

/* If an application has received an
 * -application:handleEventsForBackgroundURLSession:completionHandler:
 * message, the session delegate will receive this message to indicate
 * that all messages previously enqueued for this session have been
 * delivered.  At this time it is safe to invoke the previously stored
 * completion handler, or to begin any internal updates that will
 * result in invoking the completion handler.
 */
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session NS_AVAILABLE_IOS(7_0);

@end

有一點(diǎn)需要注意的是如果設(shè)置的NSURLSessionDataDelegate,需要在didReceiveResponse方法中加入以下代碼:

completionHandler(NSURLSessionResponseAllow);//如果不設(shè)置, 將不會(huì)執(zhí)行之后的代理方法
- (void)downloadData {
    NSURLSessionConfiguration *configura = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:configura delegate:self delegateQueue:nil];
    NSURL *url = [NSURL URLWithString:@"http://www.lxweimin.com/u/24da48b2ddb3"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request];
    [dataTask resume];
    [session finishTasksAndInvalidate];
    
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
{
    completionHandler(NSURLSessionResponseAllow);//如果不設(shè)置, 將不會(huì)執(zhí)行之后的代理方法
    NSLog(@"didReceiveResponse");
    
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
    NSLog(@"result: %@", @"didCompleteWithError");
}

文件上傳

POST每次都是以NSData的形式上傳,如果我們POST傳遞的既需要傳遞參數(shù),也需要上傳文件,就沒上面那么簡(jiǎn)單了,各位可以先想一下,實(shí)現(xiàn)如下:


- (void)originalUploadFile {
    NSDictionary *params = @{@"address"     : @"簡(jiǎn)書",
                             @"userName"    : @"FlyElephant"};
    
    NSString *path = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"jpg"];
    NSString *boundary = [self generateBoundaryString];
    
    // 請(qǐng)求的Url
    NSURL *url = [NSURL URLWithString:@"http://www.lxweimin.com/u/24da48b2ddb3"];
    
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
    [request setHTTPMethod:@"POST"];
    
    // 設(shè)置ContentType
    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
    [request setValue:contentType forHTTPHeaderField: @"Content-Type"];
    
    NSString *fieldName = @"CustomFile";
    NSData *httpBody = [self createBodyWithBoundary:boundary parameters:params paths:@[path] fieldName:fieldName];
    
    NSURLSessionTask *task = [[NSURLSession sharedSession] uploadTaskWithRequest:request fromData:httpBody completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (error) {
            NSLog(@"error = %@", error);
            return;
        }
        
        NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"FlyElephant-返回結(jié)果---result = %@", result);
    }];
    [task resume];
}

- (NSData *)createBodyWithBoundary:(NSString *)boundary
                        parameters:(NSDictionary *)parameters
                             paths:(NSArray *)paths
                         fieldName:(NSString *)fieldName {
    NSMutableData *httpBody = [NSMutableData data];
    
    // 文本參數(shù)
    
    [parameters enumerateKeysAndObjectsUsingBlock:^(NSString *parameterKey, NSString *parameterValue, BOOL *stop) {
        [httpBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
        [httpBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", parameterKey] dataUsingEncoding:NSUTF8StringEncoding]];
        [httpBody appendData:[[NSString stringWithFormat:@"%@\r\n", parameterValue] dataUsingEncoding:NSUTF8StringEncoding]];
    }];
    
    // 本地文件的NSData
    
    for (NSString *path in paths) {
        NSString *filename  = [path lastPathComponent];
        NSData   *data      = [NSData dataWithContentsOfFile:path];
        NSString *mimetype  = [self mimeTypeForPath:path];
        
        [httpBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
        [httpBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", fieldName, filename] dataUsingEncoding:NSUTF8StringEncoding]];
        [httpBody appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", mimetype] dataUsingEncoding:NSUTF8StringEncoding]];
        [httpBody appendData:data];
        [httpBody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
    }
    
    [httpBody appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    
    return httpBody;
}

- (NSString *)mimeTypeForPath:(NSString *)path {
    
    CFStringRef extension = (__bridge CFStringRef)[path pathExtension];
    CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, extension, NULL);

    NSString *mimetype = CFBridgingRelease(UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType));
    
    CFRelease(UTI);
    
    return mimetype;
}

- (NSString *)generateBoundaryString {
    return [NSString stringWithFormat:@"Boundary-%@", [[NSUUID UUID] UUIDString]];
}

實(shí)際開發(fā)中我們用到的AFNetWorking很容易就實(shí)現(xiàn)上面的代碼:


    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    NSDictionary *parameters = @{@"userName": @"FlyElphant"};
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"jpg"];
    
    [manager POST:@"http://www.lxweimin.com/u/24da48b2ddb3" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
        [formData appendPartWithFileURL:[NSURL fileURLWithPath:filePath] name:@"feature" error:nil];
    } success:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(@"FlyElephant: %@", responseObject);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"FlyElephant: %@", error);
    }];
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • NSUrlSession專題 1概述 【主要參考】NSURLSession http://blog.csdn.ne...
    Kevin_Junbaozi閱讀 4,209評(píng)論 1 15
  • 在蘋果徹底棄用NSURLConnection之后自己總結(jié)的一個(gè)網(wǎng)上的內(nèi)容,加上自己寫的小Demo,很多都是借鑒網(wǎng)絡(luò)...
    付寒宇閱讀 4,316評(píng)論 2 13
  • NSURLSession概述1. NSURLSession session類型NSURLSession包括下面3種...
    瞎嘚嘚閱讀 1,895評(píng)論 2 2
  • iOS開發(fā)系列--網(wǎng)絡(luò)開發(fā) 概覽 大部分應(yīng)用程序都或多或少會(huì)牽扯到網(wǎng)絡(luò)開發(fā),例如說新浪微博、微信等,這些應(yīng)用本身可...
    lichengjin閱讀 3,721評(píng)論 2 7
  • 每天早上睡醒時(shí)候的你 好可愛 走在上班路上的你 好可愛 和人們微笑著打招呼的你 好可愛 腮幫子鼓鼓吃零食的你 好可...
    綠竹向南閱讀 125評(píng)論 0 0