NSURLConnection connecting to server, but not post

2020-04-21 05:53发布

问题:

Whenever I attempt to post something to my PHP Server, I receive the following message. It seems as if the code is connecting to the server, but no data is returned, and the post data isn't going through. It worked through a Java App that I made, so I can assure that their is nothing wrong with my PHP. If you could help me, or need any more code to help me, just ask for it. Thanks.

Here is the code that prepares my variables for the NSURLConnection:

NSString *phash = [NSString stringWithFormat:@"%d",phashnum];
        [phash stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
name = _nameField.text;
        [name stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        email = _emailField.text;
        [email stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

Here is the code for my NSURLConnection:

NSString *urlPath = [NSString stringWithFormat:@"http://54.221.224.251"];
    NSURL *url = [NSURL URLWithString:urlPath];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    NSString *stringdata = [NSString stringWithFormat:@"name=%@&email=%@&phash=%@",name,email,phash];
    NSOperationQueue *queue= [[NSOperationQueue alloc]init];
    NSString *postData = [[NSString alloc] initWithString:stringdata];
    [request setValue:@"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:[postData dataUsingEncoding:NSUTF8StringEncoding]];
    [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        if ([data length] > 0 && connectionError==nil){
            NSLog(@"Connection Success. Data Returned");
            NSLog(@"Data = %@",data);
            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
            int code = [httpResponse statusCode];
            NSString *coder = [NSString stringWithFormat:@"%d",code];
            NSLog(@"%@",coder);
        }
        else if([data length] == 0 && connectionError == nil){
            NSLog(@"Connection Success. No Data returned.");
            NSLog(@"Connection Success. Data Returned");
            NSLog(@"Data = %@",data);
            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
            int code = [httpResponse statusCode];
            NSString *coder = [NSString stringWithFormat:@"%d",code];
            NSLog(@"%@",coder);
        }
        else if(connectionError != nil && connectionError.code == NSURLErrorTimedOut){
            NSLog(@"Connection Failed. Timed Out");
            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
            int code = [httpResponse statusCode];
            NSString *coder = [NSString stringWithFormat:@"%d",code];
            NSLog(@"%@",coder);

        }
        else if(connectionError != nil)
        {
            NSLog(@"%@",connectionError);
            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
            int code = [httpResponse statusCode];
            NSString *coder = [NSString stringWithFormat:@"%d",code];
            NSLog(@"%@",coder);

        }
    }];

Thanks in advance.

回答1:

As @elk said, you should replace spaces with +. But you should percent-encode reserved characters (as defined in RFC2396).

Unfortunately, the standard stringByAddingPercentEscapesUsingEncoding does not percent escape all of the reserved characters. For example, if the name was "Bill & Melinda Gates" or "Bill + Melinda Gates", stringByAddingPercentEscapesUsingEncoding would not percent escape the & or the + (and thus the + would have been interpreted as a space, and the & would have been interpreted as delimiting the next POST parameter).

Instead, use CFURLCreateStringByAddingPercentEscapes, supplying the necessary reserved characters in the legalURLCharactersToBeEscaped parameter and then replace the spaces with +. For example, you might define a NSString category:

@implementation NSString (PercentEscape)

- (NSString *)stringForPostParameterValue:(NSStringEncoding)encoding
{
    NSString *string = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                                                 (CFStringRef)self,
                                                                                 (CFStringRef)@" ",
                                                                                 (CFStringRef)@";/?:@&=+$,",
                                                                                 CFStringConvertNSStringEncodingToEncoding(encoding)));
    return [string stringByReplacingOccurrencesOfString:@" " withString:@"+"];
}

@end

Note, I was primarily concerned with the & and +, characters, but RFC2396 (which supersedes RFC1738) listed those additional characters as being reserved, so it's probably prudent to include all of those reserved characters in the legalURLCharactersToBeEscaped.

Pulling this together, I might have code that posts the request as:

NSDictionary *params = @{@"name" : _nameField.text ?: @"",
                         @"email": _emailField.text ?: @"",
                         @"phash": [NSString stringWithFormat:@"%d",phashnum]};

NSURL *url = [NSURL URLWithString:kBaseURLString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

[request setValue:@"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:[self httpBodyForParamsDictionary:params]];

[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
    if (error)
        NSLog(@"sendAsynchronousRequest error = %@", error);

    if (data) {
        // do whatever you want with the data
    }
}];

Using a utility method:

- (NSData *)httpBodyForParamsDictionary:(NSDictionary *)paramDictionary
{
    NSMutableArray *paramArray = [NSMutableArray array];
    [paramDictionary enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) {
        NSString *param = [NSString stringWithFormat:@"%@=%@", key, [obj stringForPostParameterValue:NSUTF8StringEncoding]];
        [paramArray addObject:param];
    }];

    NSString *string = [paramArray componentsJoinedByString:@"&"];

    return [string dataUsingEncoding:NSUTF8StringEncoding];
}


回答2:

"name=%@&email=%@&phash=%@" is not a proper url-encoded string. Each key-value pair has to be separated by an '&' character, and each key from its value by an '=' character. Keys and values are both escaped by replacing spaces with the '+' character and then encoded by stringByAddingPercentEscapesUsingEncoding.

See application/x-www-form-urlencoded.

You can find a recipe how to do this in this blog post.