AFNetworking で multipart/form-data を送る

こんな感じで使う

HogeData* data = [[HogeData alloc] init];
//data.bin = ...
//data.name = ...
//data.mimeType = ...

params = @{
    @"image": data,
    @"name": @"name"
  };

Hoge* hoge = [[Hoge alloc] init];
[hoge request:@"" method:@"GET" params:params headers: headers completionHandler:fun];

実際にリクエストするメソッド。

- (void)
    request: (NSString*)url
    method: (NSString*)method
    params: (NSDictionary*)params
    headers: (NSDictionary*)headers
    completionHandler: (Handler)func {
   
    AFHTTPRequestOperationManager* manager = [AFHTTPRequestOperationManager manager];
    
    NSMutableDictionary* strParams = [[NSMutableDictionary alloc] init];
    NSMutableDictionary* binParams = [[NSMutableDictionary alloc] init];
    
    for (NSString* key in params) {
        
        id o = [params objectForKey: key];
        
        if ([o isKindOfClass:[HogeData class]]) {
            [binParams setObject:o forKey: key];
        } else {
            [strParams setObject:o forKey: key];
        }
        
    }
    
    
    NSString* uri = [[NSURL URLWithString:url relativeToURL:manager.baseURL] absoluteString];
    
    NSError* error;
    NSMutableURLRequest *request = [manager.requestSerializer
                                    multipartFormRequestWithMethod:method
                                    URLString:uri
                                    parameters: strParams
                                    constructingBodyWithBlock:^(id<AFMultipartFormData> formData){
                                        
                                        for (NSString* key in binParams) {
                                            HogeData* data = [binParams objectForKey: key];
                                            [formData appendPartWithFileData:data.bin
                                                                        name:key
                                                                    fileName:data.fileName
                                                                    mimeType:data.mimeType];
                                        }
                                    }
                                    error:&error];
    
    [request setTimeoutInterval:_timeoutInterval];
    
    for (NSString* key in headers) {
        NSString* val = [headers objectForKey: key];
        [request addValue:val forHTTPHeaderField:key];
    }
    
    AFHTTPRequestOperation *operation = [manager
                                         HTTPRequestOperationWithRequest:request
                                         success:^(AFHTTPRequestOperation* operation, id responseObject) {
                                             func(responseObject, operation, nil);
                                         }
                                         failure:^(AFHTTPRequestOperation* operation, NSError* error) {
                                             func(nil, operation, error);
                                         }];
    
    [manager.operationQueue addOperation:operation];
}

データを表す

@interface HogeData : NSObject

@property NSString* mimeType;
@property NSString* fileName;
@property NSData* bin;

@end