如何将键值对添加到NSMutableURLRequest的主体?我知道我可以使用这样的东西:
NSURL *url = [[NSURL alloc] initWithString:@"http://localhost:8080/upload/"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:@"POST"];
NSString *bodyContents = @"fileName=";
[bodyContents stringByAppendingString:fileName];
[bodyContents stringByAppendingString:@"&"];
[bodyContents stringByAppendingString:@"deviceName="];
[bodyContents stringByAppendingString:deviceName];
[bodyContents stringByAppendingString:@"fileContents="];
[bodyContents stringByAppendingString:fileContents];
但这似乎很麻烦,特别是如果我到达我需要在请求中提交大量值的地方。我希望苹果能提供像[request addBodyField:@"fileName":fileName]
这样的方法或同样有用的方法,但是我无法在文档中找到它。有没有我遗失的或者我应该坚持附加字符串?
答案 0 :(得分:5)
问题是stringByAppendingString
不会修改字符串,而是返回包含结果的新字符串。但是,您没有将stringByAppendingString
的结果分配给任何变量,bodyContents
保持不变。
要解决此问题,您可以使用stringWithFormat
:
NSString *bodyContents = [NSString stringWithFormat:@"fileName=%@&deviceName=%@fileContents=%@", fileName, deviceName, fileContents];
或者将stringWithFormat
声明为可变字符串并使用方法appendString
:
NSMutableString *bodyContents = @"fileName=";
[bodyContents appendString:fileName];
[bodyContents appendString:@"&"];
// ...
或者在每次通话时将stringWithFormat
的结果分配给bodyContents
:
NSString *bodyContents = @"fileName=";
bodyContents = [bodyContents stringByAppendingString:fileName];
bodyContents = [bodyContents stringByAppendingString:@"&"];
// ...
答案 1 :(得分:5)
这里有很多好的答案。这就是我所做的:我构建了一个参数类,它负责配对语法和url编码。
#import "NSString+URLEncoding.h"
@interface UrlParameter ()
@property (strong, nonatomic) NSString *pair;
@property (strong, nonatomic) NSString *encodedPair;
@end
@implementation UrlParameter
@synthesize pair = _pair;
@synthesize encodedPair = _encodedPair;
+ (UrlParameter *)withName:(NSString *)name value:(NSString *)value {
UrlParameter *answer = [[UrlParameter alloc] init];
answer.pair = [NSString stringWithFormat:@"%@=%@", name, value];
answer.encodedPair = [NSString stringWithFormat:@"%@=%@", [name urlEncode], [value urlEncode]];
return answer; // autorelease if non-ARC
}
@end
这依赖于我从几篇文章中拼出的NSString类别方法。 (还准备好ARC):
@implementation NSString (URLEncoding)
- (NSString *)urlEncodeUsingEncoding:(CFStringEncoding)encoding {
return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(__bridge CFStringRef)self,
NULL,
CFSTR("!*'();:@&=+$,/?%#[]"),
encoding));
}
- (NSString *)urlEncode {
return [self urlEncodeUsingEncoding:kCFStringEncodingUTF8];
}
@end
我也是URL请求的子类,并给它可变的参数数组,然后,在它启动之前,它会这样做:
// in the interface
@property (strong, nonatomic) NSMutableArray *parameters;
- (void)prepareParameters {
NSMutableString *encodedParameterPairs = [NSMutableString stringWithCapacity:256];
int position = 1;
for (UrlParameter *requestParameter in self.parameters) {
[encodedParameterPairs appendString:[requestParameter encodedPair]];
if (position < [self.parameters count]) [encodedParameterPairs appendString:@"&"];
position++;
}
if ([[self HTTPMethod] isEqualToString:@"GET"] || [[self HTTPMethod] isEqualToString:@"DELETE"]) {
NSString *urlString = [NSString stringWithFormat:@"%@?%@", [self URLString], encodedParameterPairs];
[self setURL:[NSURL URLWithString:urlString]];
} else {
// POST, PUT
NSData *postData = [encodedParameterPairs dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
[self setHTTPBody:postData];
[self setValue:[NSString stringWithFormat:@"%d", [postData length]] forHTTPHeaderField:@"Content-Length"];
[self setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
}
}
答案 2 :(得分:3)
我推荐+ stringWithFormat。
编辑:像这样:
NSURL *url = [[NSURL alloc] initWithString:@"http://localhost:8080/upload/"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:@"POST"];
NSString *bodyContents = [NSString stringWithFormat:@"fileName=%@%@%@%@%@%@",fileName, @"&",@"deviceName=",deviceName,@"fileContents=",fileContents];
我没有必要使用任何NSMutableRequests,但是如果你需要字符串文字(\ n用于换行符的换行符\ t)或标点符号,只需将它们放在每个%@之间。
答案 3 :(得分:1)
简而言之。 创建字符串:
NSString *bodyString = [NSString stringWithFormat:@"fileName=%@&deviceName=%@&fileContents=@%", fileName, deviceName, fileContents];
格式化为NSData:
NSData *body = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
添加要求的正文:
[request setHTTPBody:body];
注意: bodyString
的格式取决于您的请求的POST格式:application/x-www-form-urlencoded
或multipart/form-data
。如果您使用multipart/form-data
- 服务器可能无法接受此格式。
答案 4 :(得分:0)
我很确定你必须使用字符串。
顺便说一句,你的字符串不是NSMutableString,所以除非你stringByAppendingString:
bodyContents = [bodyContents string...
方法实际上不会做任何事情。
stringWithFormat
是最好的方式:
NSString *bodyContents = [NSString stringWithFormat:@"fileName:%@&deviceName=%@&fileContents=%@", fileName, deviceName, fileContents"];
或者,您可以拥有一个NSArray键和一个基于该键的NSDictionary(保存值)。然后只需循环遍历NSArray并创建字符串。