2014-02-28 64 views
3

在我的應用程序中,我從服務器下載圖像作爲多部分內容。在我的回覆數據中,我得到2個部分:一個是json內容,另一個是下載文件。迴應的格式如下。在ios中解析圖像下載的多部分響應

--poa89012-3212-1232-9201-fdsakjkj921 
Content-Type: application/json; charset=utf-8 
Content-Disposition: inline; name=info 

{ 
    //json content 
} 

--poa89012-3212-1232-9201-fdsakjkj921 
Content-Disposition: file; name=file; filename=photo.png 
Content-Type: application/octet-stream 

// File data 
˘íë77íí77Í¥2008:02:11 11:32:512008:02:1 
------ 

我不能夠處理這種反應有2件,當我試圖得到didReceiveResponse標題:它給出了它的內容類型是多/ mixed.Please顯示整個響應頭我通過分割json內容和文件內容來處理這種響應的方式。

+1

任何具體原因響應使用多,如果你得到的圖像的URL會容易作爲迴應,所以你可以異步下載它。 – prasad

+0

我們只發送和接收圖像在多部分 – smily

+1

發送是好的,但對於接收沒有人使用多部分響應,因爲用戶需要等待下載整個數據,如果你使用Facebook圖形API,Twitter的API,你可以檢查他們所有做同樣的事。 – prasad

回答

5

我也有http-multipart response問題。我爲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

這應該被標記爲正確的響應 –

0

對於我來說,你的代碼沒有工作。相反,我重寫了純代碼中的代碼-c: 請注意,此代碼中的(我的)邊界總是具有額外的 - 在下一個邊界和最終邊界之前 - 這些邊界被剝離。 一個NSArray返回一個NSDictionary的每個部分,包含密鑰「頭」爲NSDictionary中和「身體」爲NSData的

- (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; 
} 
+0

如果你的部分由UTF-8和二進制數據組成,因爲它試圖將其視爲UTF-8,那麼這不起作用,二進制數據將導致initWithData函數失敗。相反,您需要根據內容類型對數據進行流式處理並分別處理每種類型的每種類型。 – possen

+0

我同意@possen。解析器在utf8轉換上失敗。 – LuAndre