NSURLSessionでBASIC認証して”PUT”or”POST”しよう!

20160203_002

さよなら、NSURLConnection第2弾は、NSURLSessionで”PUT”or”POST”です。

ファイルをアップロードするとなると、 最低限 IDとPasswordぐらいのBASIC認証はつきものBASIC認証の機能もつけちゃいます。

Xcode 7 beta5
iOS9 Beta5
Objective-C (swiftは体が拒絶反応中)

通信の準備

今回のソースコードは、アプリのtmpディレクトリー内にある test.zipを読み込みサーバーへ”PUT”です。

test.zipファイルの読み込み

tmpディレクトリーからファイル”test.zip”をNSDataで読み込み長さを取得

// tmpディレクトリ取得
NSString *tmpPath = NSTemporaryDirectory();

// 読み込みファイルフルパス作成
NSString *fileFullPath = [tmpPath stringByAppendingPathComponent:@"test.zip"];

// zipファイル読み込み
NSData *zipData     = [NSData dataWithContentsOfFile:fileFullPath];

// zipファイルの長さ
NSString *zipLength = [NSString stringWithFormat:@"%zd",[zipData length]];

// アップッロード先のフルパスを作成
NSString *serverAddressWithFileName = [@"https://xxx.testServer.com/" stringByAppendingPathComponent:@"test.zip"];

BASIC認証部作成

BASIC認証の部分を作成

// Basic認証 (base64版)
NSString *usrPass            = @"LoginID:Password";
NSData   *poolData           = [usrPass dataUsingEncoding:NSUTF8StringEncoding];
NSString *enc64Pass          = [poolData base64EncodedStringWithOptions:0];
NSString *basicWithEnc64Pass = [NSString stringWithFormat:@"Basic %@",enc64Pass];

Header部作成

「test.zip読み込み」と「BASIC認証作成」を使用してHeaderを作る
“GET”と違うのは、Headerに”PUT”するデータを仕込みます。

// Header 作成
NSMutableURLRequest *request = [NSMutableURLRequest new];
[request setURL             :[NSURL URLWithString:serverAddressWithFileName]];
[request setCachePolicy     :NSURLRequestReloadIgnoringLocalCacheData];
[request setHTTPMethod:@"PUT"];
[request setValue:@"zip"             forHTTPHeaderField:@"Content-Encoding"];
[request setValue:@"f"               forHTTPHeaderField:@"Translate"];
[request setValue:basicWithEnc64Pass forHTTPHeaderField:@"Authorization"];
[request setValue:zipLength          forHTTPHeaderField:@"Content-Length"];
[request setHTTPBody:zipData];

SessionConfigでTime Outの設定

RequestとResoruceのタイムアウト設定

// セッションコンフィグ作成
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.timeoutIntervalForRequest  = 10;
sessionConfig.timeoutIntervalForResource = 30;

NSURLSession設定

NSURLsessionの設定内容
1.sessionWithConfiguration(time out)
2.delegate
3.delegateQueue

// 通信設定
self.sessionConnect = [NSURLSession sessionWithConfiguration: sessionConfig
                                                    delegate: self
                                               delegateQueue: [NSOperationQueue mainQueue]];

dataTaskの設定

今まで作成したものをまとめ

// データタスク作成
NSURLSessionDataTask *dataTask =  [self.sessionConnect dataTaskWithRequest:request];

通信開始

NSURLSessionはこれ”resume”で通信開始

// アップロード開始
[dataTask resume];

delegate methodの設定

設定meshodは2つ

– (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^ (NSURLSessionResponseDispositiondisposition))completionHandler

– (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error

– (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^ (NSURLSessionResponseDispositiondisposition))completionHandler

いつみてもこのメソッド長すぎです。
サーバーからのレスポンス結果が返ってくるメソッドです。
今回は、response codeに”201″が帰ってくれば成功処理です。

- (void) URLSession:(NSURLSession *)session
           dataTask:(NSURLSessionDataTask *)dataTask
 didReceiveResponse:(NSURLResponse *)response
  completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {

    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;

    NSLog(@"Response Code : %zd",httpResponse.statusCode);

    // レスポンスコード [201]で通常処理で終了する。
    if (httpResponse.statusCode == 201) {
        completionHandler(NSURLSessionResponseAllow);   // 通信を続ける

    } else {
        completionHandler(NSURLSessionResponseCancel);  // 通信を止める
    }

}

– (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error

“通信成功” “通信失敗” “タイムアウト”するとこのメソッドが呼ばれます
error.codeが”0″以外は失敗扱いで処理

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {

    if (error.code == 0) {
        // アップロード成功処理

    } else {
        // アップロード失敗処理

    }

    // 終わりにする
    [session invalidateAndCancel];

}

まとめ

今回も駆け足で説明してきました。
これで、NSURLSessionマスターですね(笑)
と言ってもNSURLSessionの一部の機能です。
その他バックグラウンドで動作したりダウンロードの進行状況を取得できたりとNSURLConnectionに無い機能が盛り沢山です。

私もまだまだですがiOSの進化に負けずに頑張ってついていきたいと思います。

ソースコード

#import "testNSURLSession.h"

#define UPLOAD_SERVERADDRESS @"https://xxx.xxx.testServer.com/"
#define TIME_OUT_REQUEST  10
#define TIME_OUT_RESOURCE 30
@interface testNSURLSession ()<NSURLSessionDataDelegate>
@property (nonatomic) NSURLSession *sessionConnect;
@end

@implementation testNSURLSession

#pragma mark - 準備
- (void)uploadFileName:(NSString *)fileName {

    // tmpディレクトリ取得
    NSString *tmpPath = NSTemporaryDirectory();

    // 読み込みファイルフルパス作成
    NSString *fileFullPath = [tmpPath stringByAppendingPathComponent:fileName];

    // zipファイル読み込み
    NSData *zipData     = [NSData dataWithContentsOfFile:fileFullPath];

    if (zipData.length == 0) {
        return;
    }

    // zipファイルの長さ
    NSString *zipLength = [NSString stringWithFormat:@"%zd",[zipData length]];

    // アップッロード先のフルパスを作成
    NSString *serverAddressWithFileName = [UPLOAD_SERVERADDRESS stringByAppendingPathComponent:fileName];

    // Basic認証 (base64版)
    NSString *usrPass            = @"LoginID:Password";
    NSData   *poolData           = [usrPass dataUsingEncoding:NSUTF8StringEncoding];
    NSString *enc64Pass          = [poolData base64EncodedStringWithOptions:0];
    NSString *basicWithEnc64Pass = [NSString stringWithFormat:@"Basic %@",enc64Pass];

    // Header 作成
    NSMutableURLRequest *request = [NSMutableURLRequest new];
    [request setURL             :[NSURL URLWithString:serverAddressWithFileName]];
    [request setCachePolicy     :NSURLRequestReloadIgnoringLocalCacheData];
    [request setHTTPMethod:@"PUT"];
    [request setValue:@"zip"             forHTTPHeaderField:@"Content-Encoding"];
    [request setValue:@"f"               forHTTPHeaderField:@"Translate"];
    [request setValue:basicWithEnc64Pass forHTTPHeaderField:@"Authorization"];
    [request setValue:zipLength          forHTTPHeaderField:@"Content-Length"];
    [request setHTTPBody:zipData];

    // セッションコンフィグ作成
    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    sessionConfig.timeoutIntervalForRequest  = TIME_OUT_REQUEST;
    sessionConfig.timeoutIntervalForResource = TIME_OUT_RESOURCE;

    self.sessionConnect = [NSURLSession sessionWithConfiguration: sessionConfig
                                                        delegate: self
                                                   delegateQueue: [NSOperationQueue mainQueue]];

    // データタスク作成
    NSURLSessionDataTask *dataTask =  [self.sessionConnect dataTaskWithRequest:request];

    // アップロード開始
    [dataTask resume];
}

#pragma mark - NSURLSessin delegate
//
// レスポンス処理
- (void) URLSession:(NSURLSession *)session
           dataTask:(NSURLSessionDataTask *)dataTask
 didReceiveResponse:(NSURLResponse *)response
  completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {

    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;

    NSLog(@"Response Code : %zd",httpResponse.statusCode);

    // レスポンスコード [201]で通常処理で終了する。
    if (httpResponse.statusCode == 201) {
        completionHandler(NSURLSessionResponseAllow);   // 通信を続ける

    } else {
        completionHandler(NSURLSessionResponseCancel);  // 通信を止める
    }

}

//
// 通信成功、通信失敗の時呼ばれるメソッド
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {

    if (error.code == 0) {
        // アップロード成功を通知する

    } else {
        // アップロード失敗を通知する
    }

    // 終わりにする
    [session invalidateAndCancel];

}

@end

スポンサーリンク

シェアする

  • このエントリーをはてなブックマークに追加
  • Evernoteに保存Evernoteに保存

フォローする

スポンサーリンク