Objective-C中的简单HTTP POST示例?

53
我有一个需要登录 (用户 ID 和密码) 的 PHP 网页。我已经成功地让用户在应用程序中输入信息...但我需要一个关于如何向网站发送 POST 请求的示例。苹果支持网站上的示例相当复杂,显示了一张图片上传...我的应该更简单...我只想发布两行文本.. 有没有好的示例?
8个回答

119

这是我最近使用的方法,对我来说效果很好:

NSString *post = @"key1=val1&key2=val2";
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];

NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]];

NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:@"http://www.nowhere.com/sendFormHere.php"]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:postData];

这篇文章最初来源于http://deusty.blogspot.com/2006/11/sending-http-get-and-post-from-cocoa.html,但目前该博客似乎已经不存在了。


8
这是因为,正如vikingosekundo先生所说,Xcode与此无关,它只是你使用的集成开发环境。你正在使用Cocoa框架编写Objective-C代码。 - fresskoma
1
@Alex:您是 StackOverflow 的新手。"谢谢" 应该通过点赞来表达。 - vikingosegundo
28
5秒钟的谷歌搜索就找到了这个页面……感谢你实际回答问题而不是说“谷歌一下”。够了,别再提谷歌的评论了,天啊。 - ununiform
如果您的postData包含一个对象,您是如何处理的? - Rick Royd Aban
加1分鼓励,但事实并非总是如此简单。即使您使用纯ASCII字符,也必须添加post = [post stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];(如Naeem所述)。 - Gik
显示剩余2条评论

16

来自苹果官方网站

// In body data for the 'application/x-www-form-urlencoded' content type,
// form fields are separated by an ampersand. Note the absence of a
// leading ampersand.
NSString *bodyData = @"name=Jane+Doe&address=123+Main+St";

NSMutableURLRequest *postRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://www.apple.com"]];

// Set the request's content type to application/x-www-form-urlencoded
[postRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];

// Designate the request a POST request and specify its body data
[postRequest setHTTPMethod:@"POST"];
[postRequest setHTTPBody:[NSData dataWithBytes:[bodyData UTF8String] length:strlen([bodyData UTF8String])]];

// Initialize the NSURLConnection and proceed as described in
// Retrieving the Contents of a URL

来自:Code with Chris

    // Create the request.
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://google.com"]];

// Specify that it will be a POST request
request.HTTPMethod = @"POST";

// This is how we set header fields
[request setValue:@"application/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];

// Convert your data and set your request's HTTPBody property
NSString *stringData = @"some data";
NSData *requestBodyData = [stringData dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPBody = requestBodyData;

// Create url connection and fire request
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];

12

ASIHTTPRequest使网络通信变得非常简单易用。

ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request addPostValue:@"Ben" forKey:@"names"];
[request addPostValue:@"George" forKey:@"names"];
[request addFile:@"/Users/ben/Desktop/ben.jpg" forKey:@"photos"];
[request addData:imageData withFileName:@"george.jpg" andContentType:@"image/jpeg" forKey:@"photos"];

1
由于slug中有;,你的链接无法工作。请尝试使用http://allseeing-i.com/%5Brequest_release%5D。 - vikingosegundo
你好,如何知道FormDataRequest已完成?是否有任何requestFinished方法? - Pawriwes

4
你可以使用两个选项来完成:
使用NSURLConnection:
NSURL* URL = [NSURL URLWithString:@"http://www.example.com/path"];
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:URL];
request.HTTPMethod = @"POST";
// Form URL-Encoded Body

NSDictionary* bodyParameters = @{
    @"username": @"reallyrambody",
    @"password": @"123456"
};
request.HTTPBody = [NSStringFromQueryParameters(bodyParameters) dataUsingEncoding:NSUTF8StringEncoding];

// Connection

NSURLConnection* connection = [NSURLConnection connectionWithRequest:request delegate:nil];
[connection start];

/*
 * Utils: Add this section before your class implementation
 */

/**
 This creates a new query parameters string from the given NSDictionary. For
 example, if the input is @{@"day":@"Tuesday", @"month":@"January"}, the output
 string will be @"day=Tuesday&month=January".
 @param queryParameters The input dictionary.
 @return The created parameters string.
*/
static NSString* NSStringFromQueryParameters(NSDictionary* queryParameters)
{
    NSMutableArray* parts = [NSMutableArray array];
    [queryParameters enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
        NSString *part = [NSString stringWithFormat: @"%@=%@",
            [key stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding],
            [value stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]
        ];
        [parts addObject:part];
    }];
    return [parts componentsJoinedByString: @"&"];
}

/**
 Creates a new URL by adding the given query parameters.
 @param URL The input URL.
 @param queryParameters The query parameter dictionary to add.
 @return A new NSURL.
*/
static NSURL* NSURLByAppendingQueryParameters(NSURL* URL, NSDictionary* queryParameters)
{
    NSString* URLString = [NSString stringWithFormat:@"%@?%@",
        [URL absoluteString],
        NSStringFromQueryParameters(queryParameters)
    ];
    return [NSURL URLWithString:URLString];
}

使用NSURLSession

- (void)sendRequest:(id)sender
{
    /* Configure session, choose between:
       * defaultSessionConfiguration
       * ephemeralSessionConfiguration
       * backgroundSessionConfigurationWithIdentifier:
     And set session-wide properties, such as: HTTPAdditionalHeaders,
     HTTPCookieAcceptPolicy, requestCachePolicy or timeoutIntervalForRequest.
     */
    NSURLSessionConfiguration* sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];

    /* Create session, and optionally set a NSURLSessionDelegate. */
    NSURLSession* session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:nil delegateQueue:nil];

    /* Create the Request:
       Token Duplicate (POST http://www.example.com/path)
     */

    NSURL* URL = [NSURL URLWithString:@"http://www.example.com/path"];
    NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:URL];
    request.HTTPMethod = @"POST";

    // Form URL-Encoded Body

    NSDictionary* bodyParameters = @{
        @"username": @"reallyram",
        @"password": @"123456"
    };
    request.HTTPBody = [NSStringFromQueryParameters(bodyParameters) dataUsingEncoding:NSUTF8StringEncoding];

    /* Start a new Task */
    NSURLSessionDataTask* task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (error == nil) {
            // Success
            NSLog(@"URL Session Task Succeeded: HTTP %ld", ((NSHTTPURLResponse*)response).statusCode);
        }
        else {
            // Failure
            NSLog(@"URL Session Task Failed: %@", [error localizedDescription]);
        }
    }];
    [task resume];
}

/*
 * Utils: Add this section before your class implementation
 */

/**
 This creates a new query parameters string from the given NSDictionary. For
 example, if the input is @{@"day":@"Tuesday", @"month":@"January"}, the output
 string will be @"day=Tuesday&month=January".
 @param queryParameters The input dictionary.
 @return The created parameters string.
*/
static NSString* NSStringFromQueryParameters(NSDictionary* queryParameters)
{
    NSMutableArray* parts = [NSMutableArray array];
    [queryParameters enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
        NSString *part = [NSString stringWithFormat: @"%@=%@",
            [key stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding],
            [value stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]
        ];
        [parts addObject:part];
    }];
    return [parts componentsJoinedByString: @"&"];
}

/**
 Creates a new URL by adding the given query parameters.
 @param URL The input URL.
 @param queryParameters The query parameter dictionary to add.
 @return A new NSURL.
*/
static NSURL* NSURLByAppendingQueryParameters(NSURL* URL, NSDictionary* queryParameters)
{
    NSString* URLString = [NSString stringWithFormat:@"%@?%@",
        [URL absoluteString],
        NSStringFromQueryParameters(queryParameters)
    ];
    return [NSURL URLWithString:URLString];
}

Implicit declaration of function 'NSStringFromQueryParameters' is invalid in C99 - Nike Kov
你能为此提出改进建议吗? - Ram Suthar

2
我是iPhone应用程序的初学者,尽管我遵循了以上建议,但仍然存在问题。看起来我的服务器没有收到POST变量 - 不确定是来自php还是Objective-C代码…
Objective-C部分(按照Chris的协议方法编写)
// Create the request.
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://example.php"]];

// Specify that it will be a POST request
request.HTTPMethod = @"POST";

// This is how we set header fields
[request setValue:@"application/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];

// Convert your data and set your request's HTTPBody property
NSString *stringData = [NSString stringWithFormat:@"user_name=%@&password=%@", self.userNameField.text , self.passwordTextField.text];
NSData *requestBodyData = [stringData dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPBody = requestBodyData;

// Create url connection and fire request
//NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
NSData *response = [NSURLConnection sendSynchronousRequest:request
                                         returningResponse:nil error:nil];

NSLog(@"Response: %@",[[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding]);

在 PHP 部分以下:
if (isset($_POST['user_name'],$_POST['password'])) 

{

// Create connection
$con2=mysqli_connect($servername, $username, $password, $dbname);
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
else 
{
// retrieve POST vars
$username = $_POST['user_name'];
$password = $_POST['password'];

$sql = "INSERT INTO myTable (user_name, password) VALUES ('$username',   '$password')";
$retval = mysqli_query( $sql, $con2 );
if(! $retval )
{
die('Could not enter data: ' . mysql_error());
}
echo "Entered data successfully\n";

mysqli_close($con2);

}
}
else
{
echo "No data input in php";
}

我在这个问题上卡了好几天了。


2
 NSMutableDictionary *contentDictionary = [[NSMutableDictionary alloc]init];
[contentDictionary setValue:@"name" forKey:@"email"];
[contentDictionary setValue:@"name" forKey:@"username"];
[contentDictionary setValue:@"name" forKey:@"password"];
[contentDictionary setValue:@"name" forKey:@"firstName"];
[contentDictionary setValue:@"name" forKey:@"lastName"];

NSData *data = [NSJSONSerialization dataWithJSONObject:contentDictionary options:NSJSONWritingPrettyPrinted error:nil];
NSString *jsonStr = [[NSString alloc] initWithData:data
                                          encoding:NSUTF8StringEncoding];
NSLog(@"%@",jsonStr);

NSString *urlString = [NSString stringWithFormat:@"http://testgcride.com:8081/v1/users"];
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
   [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];


[request setHTTPBody:[jsonStr dataUsingEncoding:NSUTF8StringEncoding]];

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager.requestSerializer setAuthorizationHeaderFieldWithUsername:@"moinsam" password:@"cheese"];
manager.requestSerializer = [AFJSONRequestSerializer serializer];

AFHTTPRequestOperation *operation = [manager HTTPRequestOperationWithRequest:request success:<block> failure:<block>];

我认为这比被点赞的@"%@=%@&%@=%@&..."回答更加简洁明了。我之前不知道 dataWithJSONObject,谢谢您提供的信息。 - Alexander Tsepkov

0

这里我添加了一个示例代码,用于HTTP POST打印响应并解析为JSON(如果可能),它将异步处理所有内容,因此您的GUI将正常刷新,并且不会冻结 - 这一点很重要。

//POST DATA
NSString *theBody = [NSString stringWithFormat:@"parameter=%@",YOUR_VAR_HERE];
NSData *bodyData = [theBody dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
//URL CONFIG
NSString *serverURL = @"https://your-website-here.com";
NSString *downloadUrl = [NSString stringWithFormat:@"%@/your-friendly-url-here/json",serverURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString: downloadUrl]];
//POST DATA SETUP
[request setHTTPMethod:@"POST"];
[request setHTTPBody:bodyData];
//DEBUG MESSAGE
NSLog(@"Trying to call ws %@",downloadUrl);
//EXEC CALL
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue currentQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
    if (error) {
        NSLog(@"Download Error:%@",error.description);
    }
    if (data) {

        //
        // THIS CODE IS FOR PRINTING THE RESPONSE
        //
        NSString *returnString = [[NSString alloc] initWithData:data encoding: NSUTF8StringEncoding];
        NSLog(@"Response:%@",returnString);

        //PARSE JSON RESPONSE
        NSDictionary *json_response = [NSJSONSerialization JSONObjectWithData:data
                                                                      options:0
                                                                        error:NULL];

        if ( json_response ) {
            if ( [json_response isKindOfClass:[NSDictionary class]] ) {
                // do dictionary things
                for ( NSString *key in [json_response allKeys] ) {
                    NSLog(@"%@: %@", key, json_response[key]);
                }
            }
            else if ( [json_response isKindOfClass:[NSArray class]] ) {
                NSLog(@"%@",json_response);
            }
        }
        else {
            NSLog(@"Error serializing JSON: %@", error);
            NSLog(@"RAW RESPONSE: %@",data);
            NSString *returnString2 = [[NSString alloc] initWithData:data encoding: NSUTF8StringEncoding];
            NSLog(@"Response:%@",returnString2);
        }
    }
}];

希望这有所帮助!

0
非常感谢,它起作用了,请注意我在 PHP 中打错了一个字,应该是 mysqli_query($con2, $sql)。

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