itok's Lab

昔の開発ネタを記録として残してます

iPhotoプラグインを作る「フォト蔵編」-5 : NSURLRequest -2 : データ転送

次は、NSURLRequestでデータを転送する話。特にPOSTの場合。

これもよくわからなかったので、いろいろとネットを徘徊した結果、こちらを参考にしました。

要するに、マルチパートのメッセージを自前でこしらえる必要があるっていうだけのことなんですが、まあ、一から考えるのは手間がかかるので、既存のサンプルを参考にさせてもらったといいますか。

単純にContent-Typeをimage/jpeg固定だとして、上記ソースにちょっとだけ手を加えたものが、以下の通りです。

#define ASCII_DATA(str) [(NSString*)(str) dataUsingEncoding:NSASCIIStringEncoding]

// マルチパート生成
-(NSData*) generateFormData:(NSDictionary*)dict boundary:(NSString*)boundary
{
    NSMutableData* result = [[NSMutableData alloc] init];
    id key;
    NSEnumerator* enume = [dict keyEnumerator];

    while (key = [enume nextObject]) {
        id value = [dict valueForKey:key];
        [result appendData:ASCII_DATA(([NSString stringWithFormat:@"--%@\\n", boundary]))];
        if ([value isKindOfClass:[NSString class]]) {
            // 文字列
            // 単純に追加
            [result appendData:ASCII_DATA(([NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\\n\\n", key]))];
            [result appendData:ASCII_DATA(([NSString stringWithFormat:@"%@",value]))];
        } else if ([value class] == [NSURL class] && [value isFileURL]) {
            // データパス
            // データパス文字列を追加
            [result appendData:ASCII_DATA(([NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\\n", key, [[value path] lastPathComponent]]))];
            // Content-Type
            [result appendData:ASCII_DATA(([NSString stringWithString:@"Content-Type: image/jpeg\\n\\n"]))];
            // データの追加
            [result appendData:[NSData dataWithContentsOfFile:[value path]]];
        }
        [result appendData:ASCII_DATA(([NSString stringWithString:@"\\n"]))];
    }
    [result appendData:ASCII_DATA(([NSString stringWithFormat:@"--%@--\\n", boundary]))];
    return [result autorelease];
}

// 呼び出し側
{
    NSData* formData = [self generateFormData:params boundary:@"___boundary___"];
    [req addValue: @"multipart/form-data; boundary=___boundary___" forHTTPHeaderField: @"Content-Type"];
    [req setHTTPBody:formData];
}

とりあえず、これでファイルのPOSTはうまくいきます。