前回、mixi API を使ってmixiボイスに投稿しました。
今度はフォト付きつぶやきを投稿したかったのですが、一筋縄ではいかなくてしばらくハマっておりました。なんとかMac上のアプリとiPhone実機で送ることができたのでまとめておきます。
リクエストの作成には、前回参考にしたPythonのコードと実際のパケットをにらめっこしながらやりましたが、もっとスマートな方法があれば教えてほしいです。
フォト付きつぶやきの送り方
フォト付きつぶやきを送る方法は下記の2種類あるようで、今回は multiple/form-data 形式のリクエストで送ってみました。
Voice API << mixi Developer Center (ミクシィ デベロッパーセンター)
multiple/form-data 形式のリクエストにするためにやること
- "Content-Type"ヘッダフィールドを"multiple/form-data"にする
- RFCに沿った形でbodyを作成する
参考にしたページも載せておきます
コード例
// コンテンツの作成 NSString *boundary = @"_insert_some_boundary_here_"; NSMutableData* result = [[NSMutableData alloc] init]; [result appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSASCIIStringEncoding]]; [result appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"status\"\r\n\r\n"] dataUsingEncoding:NSASCIIStringEncoding]]; [result appendData:[[NSString stringWithFormat:@"%@",post] dataUsingEncoding:NSASCIIStringEncoding]]; [result appendData:[[NSString stringWithString:@"\r\n"] dataUsingEncoding:NSASCIIStringEncoding]]; [result appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSASCIIStringEncoding]]; [result appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"photo\"; filename=\"%@\"\r\n", fileName] dataUsingEncoding:NSASCIIStringEncoding]]; [result appendData:[[NSString stringWithString:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSASCIIStringEncoding]]; [result appendData:photo]; [result appendData:[[NSString stringWithString:@"\r\n"] dataUsingEncoding:NSASCIIStringEncoding]]; [result appendData:[[NSString stringWithFormat:@"--%@--\r\n\r\n", boundary] dataUsingEncoding:NSASCIIStringEncoding]]; // リクエストの作成 NSURL *url = [NSURL URLWithString:@"http://api.mixi-platform.com/2/voice/statuses/update"]; NSString *header = [[NSString alloc] initWithFormat:@"OAuth %@", [consumer getToken]]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:header forHTTPHeaderField:@"Authorization"]; [request setHTTPBody:result]; [request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary] forHTTPHeaderField:@"Content-Type"]; NSURLResponse *response = nil; NSError *error = nil; NSData *xoauth_response = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
簡単な解説
- boundary
- データの境界です。"Content-Type"フィールドに"multipart/form-data; boundary=
"という形で設定します。実際のbodyでは、データの開始に"-- "と設定し、すべてのデータの終端に"-- --"という形で設定します。
- データの境界です。"Content-Type"フィールドに"multipart/form-data; boundary=
- 実際のデータ
- mixi ボイスとして送信するデータ(status,photo)はboundaryのあとに「Content-Disposition: form-data; name="status"」または「Content-Disposition: form-data; name="photo"; filename="<ファイル名>"」という形で作ります。nameの部分がパラメータ名になります。フォトは一連の設定の後に実際のバイナリデータを展開することで送信できます。
- 改行
- ことろどころに改行が入っていますが、multipart/form-dataの改行コードは CRLF だそうです。改行も一つだったり二つだったりしますが、ここら辺はよくわかってないので適当に
おまけ:画像データの展開方法
今回、テスト用のMacアプリとiPhone実機に載せるアプリの両方で送信を確認しました。
送信データはNSDataとして作りますが、作成元が違うのでそれぞれのNSDataへの展開方法も載せておきます
ファイル名からNSDataを作成
NSString *fileName = @"sample.jpg";
NSData *data = [NSData dataWithContentsOfFile:fileName];
UIImageからNSDataを作成
UIImage *originalImage = ごにょごにょ; NSData *data = [[NSData alloc] initWithData:UIImagePNGRepresentation( originalImage )];