将数据添加到POST NSURLRequest

85

如何向现有的POSTNSURLRequest追加数据?我需要添加一个新参数userId=2323


3
请使用一些代码描述您的问题。 - Tirth
6个回答

195

如果您不想使用第三方类,则以下是设置帖子正文的方法...

NSURL *aUrl = [NSURL URLWithString:@"http://www.apple.com/"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:aUrl
                                         cachePolicy:NSURLRequestUseProtocolCachePolicy
                                     timeoutInterval:60.0];

[request setHTTPMethod:@"POST"];
NSString *postString = @"company=Locassa&quality=AWESOME!";
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];

NSURLConnection *connection= [[NSURLConnection alloc] initWithRequest:request 
                                                             delegate:self];

只需将您的键/值对附加到POST字符串即可。


2
我需要向现有的NSURLRequest添加新参数,而不是创建新请求。我相信它必须先转换为NSMutableURLRequest。我不知道的是如何获取现有的POST数据。 - Tim
1
换句话说,您如何获取现有请求的postString? - Tim
1
您可以访问 - (NSData *)HTTPBody,然后将其编码为NSString,键/值对。 - Simon Lee
1
这个代码 应该 能够工作,但我现在无法测试它……NSMutableString *existingPost = [[NSMutableString alloc] initWithData:[req HTTPBody] encoding:NSUTF8StringEncoding]; [existingPost appendFormat:@"&%@=%@", @"name", @"Locassa"]; - Simon Lee
“connection” 在哪里被使用了? - Arbitur
显示剩余4条评论

16

在调用NSURLConnection之前,所有对NSMutableURLRequest的更改必须完成。

当我复制并粘贴上面的代码并运行TCPMon时,我发现请求是GET而不是预期的POST

NSURL *aUrl = [NSURL URLWithString:@"http://www.apple.com/"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:aUrl
                                     cachePolicy:NSURLRequestUseProtocolCachePolicy
                                 timeoutInterval:60.0];


[request setHTTPMethod:@"POST"];
NSString *postString = @"company=Locassa&quality=AWESOME!";
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];

NSURLConnection *connection= [[NSURLConnection alloc] initWithRequest:request 
                                                         delegate:self];

13

关于构建POST请求的之前的帖子基本上是正确的(将参数添加到body中,而不是URL)。但是如果输入数据中有任何保留字符(例如空格、&和加号),那么您需要处理这些保留字符。换句话说,您应该对输入进行百分号编码。

//create body of the request

NSString *userid = ...
NSString *encodedUserid = [self percentEscapeString:userid];
NSString *postString    = [NSString stringWithFormat:@"userid=%@", encodedUserid];
NSData   *postBody      = [postString dataUsingEncoding:NSUTF8StringEncoding];

//initialize a request from url

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPBody:postBody];
[request setHTTPMethod:@"POST"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];

//initialize a connection from request, any way you want to, e.g.

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

precentEscapeString 方法的定义如下:

- (NSString *)percentEscapeString:(NSString *)string
{
    NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                                                 (CFStringRef)string,
                                                                                 (CFStringRef)@" ",
                                                                                 (CFStringRef)@":/?@!$&'()*+,;=",
                                                                                 kCFStringEncodingUTF8));
    return [result stringByReplacingOccurrencesOfString:@" " withString:@"+"];
}

请注意,曾经有一个可行的NSString方法,stringByAddingPercentEscapesUsingEncoding(现在已弃用),它可以做类似的事情,但不要尝试使用它。它处理了一些字符(例如空格字符),但没有处理其他一些字符(例如+&字符)。

当代的等效方法是stringByAddingPercentEncodingWithAllowedCharacters,但同样不要尝试使用URLQueryAllowedCharacterSet,因为它也允许+&未经转义地通过。这两个字符在更广泛的“查询”中是允许的,但如果这些字符出现在查询内的值中,则必须进行转义。从技术上讲,您可以使用URLQueryAllowedCharacterSet来构建可变字符集并删除其中包含的一些字符,或者从头开始构建自己的字符集。

例如,如果您查看Alamofire的参数编码,他们使用URLQueryAllowedCharacterSet,然后移除generalDelimitersToEncode(其中包括字符#[]@,但由于一些旧的Web服务器中存在历史性的bug,?/没有被移除)和subDelimitersToEncode(即!$&'()*+,;=)。这是正确的实现(虽然您可以争论是否应该移除?/),但相当复杂。也许CFURLCreateStringByAddingPercentEscapes更直接/高效。


关于 stringByAddingPercentEscapesUsingEncoding: 是真的,但是 stringByAddingPercentEncodingWithAllowedCharacters: 可以处理每个字符。 例如:URLString = [URLString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; - Alejandro Cotilla
@AlejandroDavidCotillaRojas - 您可以使用 stringByAddingPercentEncodingWithAllowedCharacters,但不能使用 URLQueryAllowedCharacterSet,因为它包括 +&(这些是更广泛的查询中允许的字符,但如果这些字符出现在查询中的值中,则必须进行转义,而该字符集不会这样做)。因此,您可以使用 URLQueryAllowedCharacterSet 来构建可变字符集并删除其中包含的一些字符,或者从头开始构建自己的字符集。或者使用 CFURLCreateStringByAddingPercentEscapes - Rob
非常好的答案,真正为使用Alamofire避免所有这些深度提出了论据! - Dan Rosenstark
鉴于CFURLCreateStringByAddingPercentEscapes现已被弃用,您真的应该自己构建适当的字符集。请参见https://stackoverflow.com/a/54742187/1271826。 - Rob

8
 NSURL *url= [NSURL URLWithString:@"https://www.paypal.com/cgi-bin/webscr"];
 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:aUrl
                                                        cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                    timeoutInterval:10.0];
[request setHTTPMethod:@"POST"];
 NSString *postString = @"userId=2323";
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];

8

上面的示例代码对我非常有帮助,但是(如上所提到的),我认为你需要使用NSMutableURLRequest而不是NSURLRequest。在当前形式下,我无法让它响应setHTTPMethod调用。更改类型可以解决问题。


2

如果你正在寻找一个快速的解决方案,

let url = NSURL(string: "http://www.apple.com/")
let request = NSMutableURLRequest(URL: url!)
request.HTTPBody = "company=Locassa&quality=AWESOME!".dataUsingEncoding(NSUTF8StringEncoding)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接