5

我在 ios 中创建了一个用户查询表单。我使用 php 作为服务器端。我在IOS中构造了如下查询字符串

http://www.mydomain.in/androidmail_enquiry.php?name=Vinoth Kumar&phone=04259280244&email=vinoth@ldomain.com&address=Coimbatore&comments=Sample Enquiry&mobile=xxxxxxxx

代码:

-(void)sendEnquiryDetails
{
    cmttextview.text = @"Sample Enquiry";
    NSString *siteurl = @"http://www.mydomain.in/androidmail_enquiry.php?";
    NSString *name = txtName.text;
    NSString *phone = txtPhone.text;
    NSString *email = txtEmail.text;
    NSString *address = txtAddress.text;
    NSString *comments = cmttextview.text;
    NSString *mobile = txtMobile.text;
    NSString *enquiryurl = [NSString stringWithFormat:@"%@name=%@&phone=%@&email=%@&address=%@&comments=%@&mobile=%@",siteurl,name,phone,email,address,comments,mobile];

    NSLog(enquiryurl);

   NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:enquiryurl]];
    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request  delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    //NSLog(@"didReceiveResponse");
    [self.responseData setLength:0];
}

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [self.responseData appendData:data];
}

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"%@",[NSString stringWithFormat :@"didfailwitherror: %@", [error description]]);
}

-(void)connectionDidFinishLoading: (NSURLConnection *)connection{
    NSLog(@"Success Code:%@",self.responseData);
}

但是当我通过使用 NSURLRequest 提交此错误时,在 didFailWithError 方法中出现无效 url(URL 形成错误)之类的错误。

4

3 回答 3

7

确保您已添加stringByAddingPercentEscapesUsingEncoding,因为在您的 url 中有 name 空格,因此在浏览器中它被替换为 %20 您必须以编程方式在代码中添加,

尝试这个

-(void)sendEnquiryDetails
{
    cmttextview.text = @"Sample Enquiry";
    NSString *siteurl = @"http://www.mydomain.in/androidmail_enquiry.php?";
    NSString *name = txtName.text;
    NSString *phone = txtPhone.text;
    NSString *email = txtEmail.text;
    NSString *address = txtAddress.text;
    NSString *comments = cmttextview.text;
    NSString *mobile = txtMobile.text;
    NSString *enquiryurl = [NSString stringWithFormat:@"%@name=%@&phone=%@&email=%@&address=%@&comments=%@&mobile=%@",siteurl,name,phone,email,address,comments,mobile];

    NSLog(enquiryurl);

 NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[enquiryurl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request  delegate:self];
}
于 2013-10-09T04:45:55.320 回答
5

You have to percent escape reserved characters. If nothing else, you have to replace those spaces with + (or %20).

Unfortunately, the standard stringByAddingPercentEscapesUsingEncoding is not up to the job, as it leaves some characters unescaped. Your sample doesn't include any of them, but if the person's name was entered as "Bill & Melinda Gates" or "Bill + Melinda Gates", stringByAddingPercentEscapesUsingEncoding would not handle that properly. You really should use CFURLCreateStringByAddingPercentEscapes to percent escape the values, for example using this category:

@implementation NSString (URLEncode)

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

@end

This properly escapes all reserved characters, but replaces spaces with + characters (which you should do if your request type is application/x-www-form-urlencoded).

Alternatively, you can also replace the space characters with %20 like so:

- (NSString *)stringForHTTPRequest
{
    return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                                     (CFStringRef)self,
                                                                     NULL,
                                                                     (CFStringRef)@":/?@!$&'()*+,;=",
                                                                     kCFStringEncodingUTF8));
}

With that, you could modify that line of code that builds the URL string:

NSString *enquiryurl = [NSString stringWithFormat:@"%@name=%@&phone=%@&email=%@&address=%@&comments=%@&mobile=%@",
                        siteurl, 
                        [name stringForHTTPRequest],
                        [phone stringForHTTPRequest],
                        [email stringForHTTPRequest],
                        [address stringForHTTPRequest],
                        [comments stringForHTTPRequest],
                        [mobile stringForHTTPRequest]];
于 2013-10-09T04:51:31.460 回答
2

根据文档,如果NSURL使用字符串初始化对象,则字符串必须符合RFC 2396(请参阅 Apple 官方文档URLWithString)。

然而,最新的 RFC 是RFC 3986,它淘汰了 RFC 2396。

警告:

不过,Cocoa 和 Core Foundation 都不会有一个开箱即用的函数返回一个正确编码的符合 RFC 2396 或 RFC 3986 的 URL 字符串。

URL 的不同组件具有不同的百分比编码要求。

编辑:

为了在 URL 的非结构化查询组件中传输结构化参数,可以将等同于application/x-www-form-urlencoded 编码算法的编码 方案应用于查询组件。

对名称进行编码并符合该编码的辅助函数可以实现为:

static NSString* urlformdata_encode(NSString* s) {
    CFStringRef charactersToLeaveUnescaped = CFSTR(" ");
    CFStringRef legalURLCharactersToBeEscaped = CFSTR("!$&'()+,/:;=?@~");
    
    NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
                             kCFAllocatorDefault,
                             (__bridge CFStringRef)s,
                             charactersToLeaveUnescaped,
                             legalURLCharactersToBeEscaped,
                             kCFStringEncodingUTF8));
    return [result stringByReplacingOccurrencesOfString:@" " withString:@"+"];
}

(注意:此代码取决于 的当前实现CFURLCreateStringByAddingPercentEscapes,尤其是其默认转义。如果这些更改,代码可能无法正确实现算法。)

根据 RFC 3986,queryURL 的组件被视为仅包含 ASCII 字符的非结构化百分比编码字节流。

最初,已经定义了“application/x-www-form-urlencoded”编码方案,用于将表单数据从浏览器传输到服务器,该服务器成为正文的有效负载。也就是说,上下文与 URL 完全不同。尽管如此,即使这种编码方案没有在 RFC 3986 中定义,它最终还是与 URL 编码方案兼容。

注意事项

“application/x-www-form-urlencoded” 编码方案可能会为现在位于根据 RFC 3986 的“未保留”字符集中的字符(即波浪~字符)产生百分比转义。“未保留”字符集中的字符不需要转义。更严格地说,由于对 URI 比较实现的影响,RFC 3986 提出了以下建议:

“为了保持一致性,在 ALPHA(%41-%5A 和 %61-%7A)、DIGIT(%30-%39)、连字符(%2D)、句点(%2E)、下划线( URI 生产者不应创建 %5F) 或波浪号 (%7E)”

为了不在~查询参数中转义波浪号,可以~从要转义的一组合法 URL 字符中删除波浪号legalURLCharactersToBeEscaped

CFStringRef legalURLCharactersToBeEscaped = CFSTR("!$&'()+,/:;=?@");

即使根据“application/x-www-form-urlencoded encoding”算法并不严格,不转义波浪号也不应该引起问题。

与此问题的其他建议算法的差异:

由于“application/x-www-form-urlencoded”解码算法将任何百分比解码的字符序列解码为其相应的Unicode代码单元,因此在编码期间legalURLCharactersToBeEscaped指定的集合中的差异最终可能会产生相等的字符串。CFURLCreateStringByAddingPercentEscapes

(编辑:删除了对 URL 的组件进行编码的辅助函数,当查询字符串应通过application/x-www-form-urlencoded编码时,这些组件不相关)

于 2013-10-09T10:55:30.507 回答