0

我正在尝试通过数据库上的 HTTP Post webservice 获取 CSV 文件,以便我可以解析它。我目前有这个代码

-(void)viewDidLoad{
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://192.x.x.x/xyz.php?cmd=select * from record and datetime>'%@ 00:00:00' and datetime<'%@ 23:59:59' order by id limit 15", startDate, endDate]]];
    [request setHTTPMethod:@"POST"];

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

    if(conn)
    {
        NSLog(@"Connection Successful");
    }
    else
    {
        NSLog(@"Connection could not be made");
    }}
    ////////////////////////////
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    NSLog(@"Did Receive Data method was called");
    NSString *contentString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    csvParser = [[CHCSVParser alloc] initWithContentsOfCSVFile:contentString];

    ParserDelegate *parserDelegate = [[ParserDelegate alloc] initParser];
    [csvParser setDelegate: parserDelegate];
    [csvParser parse];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"Error: %@", error);
}

这是我从调试日志中得到的

 Command string: http://192.x.x.x/xyz.php?cmd=select * from record and datetime>'2003-10-30 08:00:00 +0000 00:00:00' and datetime<'2013-10-29 07:00:00 +0000 23:59:59' order by id limit 15
[615:c07] Connection Successful
[615:c07] Error: Error Domain=NSURLErrorDomain Code=-1000 "bad URL" UserInfo=0x7561fd0 {NSUnderlyingError=0x71eb1c0 "bad URL", NSLocalizedDescription=bad URL}

我收到了这个错误的 URL。我可以通过网络浏览器访问 URL(浏览器可能会做一些事情)。有谁知道问题是什么以及如何解决?

谢谢

4

1 回答 1

1

您需要对查询进行百分比编码:

您的查询包含一个参数(键/值):

key:   @"cmd"
value: @"select * from record and datetime>'%@ 00:00:00' and datetime<'%@ 23:59:59' order by id limit 15"

键和值在组合成参数字符串之前需要正确编码。参数字符串将由编码键、“=”和编码值组成。

可以在此处找到对一个键或值进行编码的算法:application/x-www-form-urlencoded encoding algorithm

另请参见RFC 3986

为了对参数值或参数键进行编码,您可以使用此辅助函数,如此答案所示:(无法从 NSString 创建 NSUrl 总是为零

笔记:

通常,POST 请求会将查询参数放入请求正文中。但是,该标准并未明确禁止这一点。POST 请求与 URL 中的查询参数字符串一起使用。

话虽如此,可能更好的方法是将查询放入正文中:

您可以将正文的内容类型设置为“application/x-www-form-urlencoded”(在标头中),然后使用相同的编码算法。

所以,如果你想尝试“application/x-www-form-urlencoded”:

  1. Content-Type请求的标头设置为“application/x-www-form-urlencoded”
  2. 如上所述序列化您的查询参数。
  3. 从生成的查询字符串中获取一个NSData使用 UTF-8 编码的对象,并使用此数据设置请求的正文。

或者,您可以尝试其他内容类型,例如 JSON。这是否可能取决于服务器的功能。老实说,内容类型“application/json”可能是首选方式。

所以,如果你想尝试“application/json”:

  1. Content-Type请求的设置为“application/json”

  2. 将您的查询参数序列化为 JSON 对象,例如:

    id jsonObject = @{@"cmd": @"select * from ... limit 15"};

    利用NSJSONSerializationNSData在 UTF-8 中获取包含 JSON 的位置。

  3. 使用此数据设置请求的正文。

在这两种方法中,您还应该设置Content-Length标头,即主体数据的长度(以字节为单位)。

辅助函数

以下帮助函数返回参数的编码名称字符串编码值字符串

static NSString* form_urlencode_rfc3986(NSString* s) {
    CFStringRef charactersToLeaveUnescaped = CFSTR(" ");
    //CFStringRef legalURLCharactersToBeEscaped = CFSTR("!$&'()+,/:;=?@~");
    // Modified for urls (excluding '~'):
    CFStringRef legalURLCharactersToBeEscaped = CFSTR("!$&'()+,/:;=?@");

    NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
                             kCFAllocatorDefault,
                             (__bridge CFStringRef)s,
                             charactersToLeaveUnescaped,
                             legalURLCharactersToBeEscaped,
                             kCFStringEncodingUTF8));
    return [result stringByReplacingOccurrencesOfString:@" " withString:@"+"];
}

为了组成(编码的)参数字符串,将“=”附加到编码名称,然后附加编码值。

为了组成一个(编码的)查询字符串,通过用“&”分隔所有编码的参数字符串来连接它们。

于 2013-10-29T18:25:33.523 回答