Parse multipart response for image download in ios

前端 未结 2 1645
一整个雨季
一整个雨季 2020-12-03 19:53

In my application, I\'m downloading image from server as multipart content. In my response data I\'m getting 2 parts: one is json content and other is downloaded file. The r

相关标签:
2条回答
  • 2020-12-03 20:17

    I also did have problems with http-multipart response. I wrote a category for NSData. Code below:

    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
    
    0 讨论(0)
  • 2020-12-03 20:32

    For me, your code didn't work. Instead, I rewrote that code in pure objective-c: Take care that (my) boundaries in this code always have additional -- in front of the next boundary and a final boundary - those are stripped. An NSArray is returned with a NSDictionary for each part, containing the keys "headers" as NSDictionary and "body" as 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 讨论(0)
提交回复
热议问题