2013-09-05 6 views
1

웹 서비스에서 http-multipart 응답을 수신해야합니다. JSON과 이미지의 쌍으로 된 멀티 파트 응답.http-multipart 응답 구문 분석

두 부분으로 응답을 처리하는 방법 (JSON의 경우 NSDictionary, 이미지의 경우 NSData)?

미리 감사드립니다.

[업데이트] NSData 카테고리를 작성했습니다. 아래 코드 :

을 NSData + MultipartResponses.h

#import <Foundation/Foundation.h> 

@interface NSData (MultipartResponses) 

- (NSArray *)multipartArray; 
- (NSDictionary *)multipartDictionary; 

@end 

을 NSData + MultipartResponses.m 나를 위해

#import "NSData+MultipartResponses.h" 

@implementation NSData (MultipartResponses) 

static NSMutableDictionary *parseHeaders(const char *headers) 
{ 
    NSMutableDictionary *dict=[NSMutableDictionary dictionary]; 
    int max=strlen(headers); 
    int start=0; 
    int cursor=0; 
    while(cursor<max) 
    { 
     while((headers[cursor]!=':')&&(headers[cursor]!='=')) 
     { 
     cursor++; 
     } 
     NSString *key=[[NSString alloc] initWithBytes:(headers+start) length:(cursor-start) encoding:NSASCIIStringEncoding]; 
     cursor++; 

     while(headers[cursor]==' ') 
     { 
     cursor++; 
     } 
     start=cursor; 
     while(headers[cursor]&&(headers[cursor]!=';')&&((headers[cursor]!=13)||(headers[cursor+1]!=10))) 
     { 
     cursor++; 
     } 

     NSString *value; 
     if((headers[start]=='"')&&(headers[cursor-1]=='"')) 
     { 
     value=[[NSString alloc] initWithBytes:(headers+start+1) length:(cursor-start-2) encoding:NSASCIIStringEncoding]; 
     } 
     else 
     { 
     value=[[NSString alloc] initWithBytes:(headers+start) length:(cursor-start) encoding:NSASCIIStringEncoding]; 
     } 
     [dict setObject:value forKey:key]; 

     if(headers[cursor]==';') 
     { 
     cursor++; 
     } 
     else 
     { 
     cursor+=2; 
     } 

     while(headers[cursor]==' ') 
     { 
     cursor++; 
     } 
     start=cursor; 
    } 
    return dict; 
} 

- (NSDictionary *)multipartDictionaryWithBoundary:(NSString *)boundary 
{ 
    NSMutableDictionary *dict=[NSMutableDictionary dictionary]; 

    const char *bytes=(const char *)[self bytes]; 
    const char *pattern=[boundary cStringUsingEncoding:NSUTF8StringEncoding]; 

    int cursor=0; 
    int start=0; 
    int max=[self length]; 
    int keyNo=0; 
    while(cursor<max) 
    { 
     if(bytes[cursor]==pattern[0]) 
     { 
     int i; 
     int patternLength=strlen(pattern); 
     BOOL match=YES; 
     for(i=0; i<patternLength; i++) 
     { 
      if(bytes[cursor+i]!=pattern[i]) 
      { 
       match=NO; 
       break; 
      } 
     } 
     if(match) 
     { 
      if(start!=0) 
      { 
       int startOfHeaders=start+2; 
       int cursor2=startOfHeaders; 
       while((bytes[cursor2]!=(char)0x0d)||(bytes[cursor2+1]!=(char)0x0a)||(bytes[cursor2+2]!=(char)0x0d)||(bytes[cursor2+3]!=(char)0x0a)) 
       { 
        cursor2++; 
        if(cursor2+4==max) 
        { 
        break; 
        } 
       } 
       if(cursor2+4==max) 
       { 
        break; 
       } 
       else 
       { 
        int lengthOfHeaders=cursor2-startOfHeaders; 
        char *headers=(char *)malloc((lengthOfHeaders+1)*sizeof(char)); 
        strncpy(headers, bytes+startOfHeaders, lengthOfHeaders); 
        headers[lengthOfHeaders]=0; 

        NSMutableDictionary *item=parseHeaders(headers); 

        int startOfData=cursor2+4; 
        int lengthOfData=cursor-startOfData-2; 

        if(([item valueForKey:@"Content-Type"]==nil)&&([item valueForKey:@"filename"]==nil)) 
        { 
        NSString *string=[[NSString alloc] initWithBytes:(bytes+startOfData) length:lengthOfData encoding:NSUTF8StringEncoding]; 
        keyNo++; 
        [dict setObject:string forKey:[NSString stringWithFormat:@"%d", keyNo]]; 
        } 
        else 
        { 
        NSData *data=[NSData dataWithBytes:(bytes+startOfData) length:lengthOfData]; 
        [item setObject:data forKey:@"data"]; 
        keyNo++; 
        [dict setObject:item forKey:[NSString stringWithFormat:@"%d", keyNo]]; 
        } 
       } 
      } 
      cursor=cursor+patternLength-1; 
      start=cursor+1; 
     } 
     } 
     cursor++; 
    } 

    return dict; 
} 

- (NSArray *)multipartArray 
{ 
    NSDictionary *dict=[self multipartDictionary]; 
    NSArray *keys=[[dict allKeys] sortedArrayUsingSelector:@selector(localizedStandardCompare:)]; 
    NSMutableArray *array=[NSMutableArray array]; 
    for(NSString *key in keys) 
    { 
     [array addObject:dict[key]]; 
    } 
    return array; 
} 

- (NSDictionary *)multipartDictionary 
{ 
    const char *bytes=(const char *)[self bytes]; 
    int cursor=0; 
    int max=[self length]; 
    while(cursor<max) 
    { 
     if(bytes[cursor]==0x0d) 
     { 
     break; 
     } 
     else 
     { 
     cursor++; 
     } 
    } 
    char *pattern=(char *)malloc((cursor+1)*sizeof(char)); 
    strncpy(pattern, bytes, cursor); 
    pattern[cursor]=0x00; 
    NSString *boundary=[[NSString alloc] initWithCString:pattern encoding:NSUTF8StringEncoding]; 
    free(pattern); 
    return [self multipartDictionaryWithBoundary:boundary]; 
} 

@end 

답변

1

, 코드가 작동하지 않았다. 대신 코드를 순수한 목적으로 다시 작성했습니다.- 이 코드의 (내) 경계선은 항상 다음 경계선과 최종 경계선 앞에 추가됩니다. 즉, 경계선이 제거됩니다. "Headers"키가 NSDictionary이고 "body"가 NSData 인 NSDictionary와 함께 NSArray가 반환됩니다.

- (NSArray *)multipartArrayWithBoundary:(NSString *)boundary 
{ 
    NSString *data = [[[NSString alloc] initWithData:self encoding:NSUTF8StringEncoding] autorelease]; 

    NSArray *multiparts = [data componentsSeparatedByString:[@"--" stringByAppendingString:boundary]]; // remove boundaries 
    multiparts = [multiparts subarrayWithRange:NSMakeRange(1, [multiparts count]-2)]; // continued removing of boundaries 

    NSMutableArray *toReturn = [NSMutableArray arrayWithCapacity:2]; 
    for(NSString *part in multiparts) 
    { 
     part = [part stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 
     NSArray *separated = [part componentsSeparatedByString:@"\n\n"]; 

     NSMutableDictionary *headers = [NSMutableDictionary dictionaryWithCapacity:3]; 
     for(NSString *headerLine in [[separated objectAtIndex:0] componentsSeparatedByString:@"\n"]) 
     { 
      NSArray *keyVal = [headerLine componentsSeparatedByString:@":"]; 

      [headers setObject:[[keyVal objectAtIndex:1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] forKey:[[keyVal objectAtIndex:0] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]]; 
     } 

     [toReturn addObject:[NSDictionary dictionaryWithObjectsAndKeys:[[separated objectAtIndex:1] dataUsingEncoding:NSUTF8StringEncoding], @"body", headers, @"headers", nil]]; 
    } 

    return toReturn; 
}