gpt4 book ai didi

ios - 解析 http 多部分响应

转载 作者:可可西里 更新时间:2023-11-01 17:10:36 24 4
gpt4 key购买 nike

我需要从 Web 服务接收 http 多部分响应。包含成对的 JSON 和图像的多部分响应。

如何分两部分处理响应(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

最佳答案

对我来说,您的代码不起作用。相反,我用纯 objective-c 重写了该代码:请注意,此代码中的(我的)边界总是有额外的 - 在下一个边界和最终边界之前 - 那些被剥离。返回一个 NSArray,每个部分都有一个 NSDictionary,包含作为 NSDictionary 的键“headers”和作为 NSData 的“body”

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

关于ios - 解析 http 多部分响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18643018/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com