【问题标题】:Sending an HTTP POST request on iOS在 iOS 上发送 HTTP POST 请求
【发布时间】:2013-04-01 18:42:07
【问题描述】:

我正在尝试使用我正在开发的 iOS 应用程序发送 HTTP Post,但推送从未到达服务器,尽管我确实收到了代码 200 作为响应(来自 urlconnection)。我从来没有得到服务器的响应,服务器也没有检测到我的帖子(服务器确实检测到来自 android 的帖子)

我确实使用 ARC,但已将 pd 和 urlConnection 设置为强。

这是我发送请求的代码

 NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
                                    initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@%@",dk.baseURL,@"daantest"]]];
    [request setHTTPMethod:@"POST"];
    [request setValue:@"text/xml"
   forHTTPHeaderField:@"Content-type"];

    NSString *sendString = @"<data><item>Item 1</item><item>Item 2</item></data>";

    [request setValue:[NSString stringWithFormat:@"%d", [sendString length]] forHTTPHeaderField:@"Content-length"];

    [request setHTTPBody:[sendString dataUsingEncoding:NSUTF8StringEncoding]];
    PushDelegate *pushd = [[PushDelegate alloc] init];
    pd = pushd;
    urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:pd];
    [urlConnection start];

这是我的委托代码

#import "PushDelegate.h"

@implementation PushDelegate
@synthesize data;

-(id) init
{
    if(self = [super init])
    {
        data = [[NSMutableData alloc]init];
        [data setLength:0];
    }
    return self;
}


- (void)connection:(NSURLConnection *)connection didWriteData:(long long)bytesWritten totalBytesWritten:(long long)totalBytesWritten
{
    NSLog(@"didwriteData push");
}
- (void)connectionDidResumeDownloading:(NSURLConnection *)connection totalBytesWritten:(long long)totalBytesWritten expectedTotalBytes:(long long)expectedTotalBytes
{
    NSLog(@"connectionDidResumeDownloading push");
}

- (void)connectionDidFinishDownloading:(NSURLConnection *)connection destinationURL:(NSURL *)destinationURL
{
    NSLog(@"didfinish push @push %@",data);
}

- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
{
    NSLog(@"did send body");
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    [self.data setLength:0];
    NSHTTPURLResponse *resp= (NSHTTPURLResponse *) response;
    NSLog(@"got response with status @push %d",[resp statusCode]);
}

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

    NSLog(@"recieved data @push %@", data);
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSString *responseText = [[NSString alloc] initWithData:self.data encoding:NSUTF8StringEncoding];

    NSLog(@"didfinishLoading%@",responseText);

}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error ", @"")
                                message:[error localizedDescription]
                               delegate:nil
                      cancelButtonTitle:NSLocalizedString(@"OK", @"")
                      otherButtonTitles:nil] show];
    NSLog(@"failed &push");
}

// Handle basic authentication challenge if needed
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
    NSLog(@"credentials requested");
    NSString *username = @"username";
    NSString *password = @"password";

    NSURLCredential *credential = [NSURLCredential credentialWithUser:username
                                                             password:password
                                                          persistence:NSURLCredentialPersistenceForSession];
    [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}

@end

控制台总是打印以下行并且只打印以下行:

2013-04-01 20:35:04.341 ApprenticeXM[3423:907] did send body
2013-04-01 20:35:04.481 ApprenticeXM[3423:907] got response with status @push 200
2013-04-01 20:35:04.484 ApprenticeXM[3423:907] didfinish push @push <>

【问题讨论】:

    标签: ios objective-c automatic-ref-counting http-post nsurlconnection


    【解决方案1】:

    以下代码描述了一个使用POST方法的简单示例。(如何通过POST方法传递数据

    在这里,我描述了如何使用 POST 方法。

    1.用实际的用户名和密码设置帖子字符串。

    NSString *post = [NSString stringWithFormat:@"Username=%@&Password=%@",@"username",@"password"]; 
    

    2. 使用NSASCIIStringEncoding 编码post 字符串以及您需要以NSData 格式发送的post 字符串。

    NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; 
    

    您需要发送数据的实际长度。计算帖子字符串的长度。

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

    3. 创建一个带有所有属性的 Urlrequest,例如 HTTP 方法、带有帖子字符串长度的 http 标头字段。创建URLRequest 对象并对其进行初始化。

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; 
    

    设置要向该请求发送数据的 URL。

    [request setURL:[NSURL URLWithString:@"http://www.abcde.com/xyz/login.aspx"]]; 
    

    现在,设置 HTTP 方法(POST 或 GET)。按照您的代码中的方式编写这些行。

    [request setHTTPMethod:@"POST"]; 
    

    HTTP 标头字段设置为发布数据的长度。

    [request setValue:postLength forHTTPHeaderField:@"Content-Length"]; 
    

    同时设置 HTTP 标头字段的编码值。

    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    

    用postData设置urlrequest的HTTPBody

    [request setHTTPBody:postData];
    

    4. 现在,创建 URLConnection 对象。使用 URLRequest 对其进行初始化。

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

    它返回初始化的 url 连接并开始为 url 请求加载数据。您可以使用以下 if/else 语句检查您的URL 连接是否正确完成。

    if(conn) {
        NSLog(@"Connection Successful");
    } else {
        NSLog(@"Connection could not be made");
    }
    

    5. 要接收来自 HTTP 请求的数据,您可以使用 URLConnection 类参考提供的委托方法。 委托方法如下。

    // This method is used to receive the data which we get using post method.
    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData*)data
    
    // This method receives the error report in case of connection is not made to server. 
    - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
    
    // This method is used to process the data after connection has made successfully.
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection
    

    另请参阅 This This 文档了解POST 方法。

    这是HTTPPost Method.源代码的最佳示例

    【讨论】:

    • 同时检查是否没有缓存。这可以解释为什么你得到一个“200”,而服务器上没有任何事情发生。
    • 检查stackoverflow.com/questions/405151/… 和/或谷歌接受的答案以获取“nsurlconnection 缓存策略”
    • 虽然这个答案已经被接受了这么多次,但这个答案中给出的代码有很多明显的问题,在实践中会很麻烦。
    • @iPatel 但是我们可以使用上面给出的 post 方法代码发送图像数据吗?
    • 很遗憾,这段代码不正确,容易受到注入攻击。如果用户在密码中碰巧有一个“&”字符,则所有其他字符都将被解析为附加的 POST 参数。故意操纵是可能的。
    【解决方案2】:
    -(void)sendingAnHTTPPOSTRequestOniOSWithUserEmailId: (NSString *)emailId withPassword: (NSString *)password{
    //Init the NSURLSession with a configuration
    NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: nil delegateQueue: [NSOperationQueue mainQueue]];
    
    //Create an URLRequest
    NSURL *url = [NSURL URLWithString:@"http://www.example.com/apis/login_api"];
    NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
    
    //Create POST Params and add it to HTTPBody
    NSString *params = [NSString stringWithFormat:@"email=%@&password=%@",emailId,password];
    [urlRequest setHTTPMethod:@"POST"];
    [urlRequest setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]];
    
    //Create task
    NSURLSessionDataTask *dataTask = [defaultSession dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        //Handle your response here
        NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
         NSLog(@"%@",responseDict);
    }];
       [dataTask resume];
    }
    

    【讨论】:

      【解决方案3】:

      我不太清楚为什么,但只要我注释掉以下方法就可以了:

      connectionDidFinishDownloading:destinationURL:
      

      此外,我认为您不需要来自 NSUrlConnectionDownloadDelegate 协议的方法,只需要来自 NSURLConnectionDataDelegate 的方法,除非您需要一些下载信息。

      【讨论】:

      • 我确实想要下载信息,这就是为什么我有函数 connectionDidFinishDownloading:destinationURL:
      • 显然 NSURLConnectionDownloadDelegate 仅适用于报亭应用程序......至少这是这个线程所说的:stackoverflow.com/questions/6735121/…
      【解决方案4】:

      这是我在日志库中使用的方法:https://github.com/goktugyil/QorumLogs

      此方法填充 Google 表单中的 html 表单。希望它对使用 Swift 的人有所帮助。

      var url = NSURL(string: urlstring)
      
      var request = NSMutableURLRequest(URL: url!)
      request.HTTPMethod = "POST"
      request.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
      request.HTTPBody = postData.dataUsingEncoding(NSUTF8StringEncoding)
      var connection = NSURLConnection(request: request, delegate: nil, startImmediately: true)
      

      【讨论】:

        【解决方案5】:

        在 iOS 上发送 HTTP POST 请求(目标 c):

        -(NSString *)postexample{
        
        // SEND POST
        NSString *url = [NSString stringWithFormat:@"URL"];
        NSString *post = [NSString stringWithFormat:@"param=value"];
        NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
        NSString *postLength = [NSString stringWithFormat:@"%d",[postData length]];
        
        
        NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
        [request setHTTPMethod:@"POST"];
        [request setURL:[NSURL URLWithString:url]];
        [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
        [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
        [request setHTTPBody:postData];
        
        NSError *error = nil;
        NSHTTPURLResponse *responseCode = nil;
        
        //RESPONDE DATA 
        NSData *oResponseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&responseCode error:&error];
        
        if([responseCode statusCode] != 200){
            NSLog(@"Error getting %@, HTTP status code %li", url, (long)[responseCode statusCode]);
            return nil;
        }
        
        //SEE RESPONSE DATA
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Response" message:[[NSString alloc] initWithData:oResponseData encoding:NSUTF8StringEncoding] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
        [alert show];
        
        return [[NSString alloc] initWithData:oResponseData encoding:NSUTF8StringEncoding];
        }
        

        【讨论】:

        • 这是新的......在您的问题发布 4 年后得到回复:p
        • 这个“postexample”函数比Response更快:p @DaanLuttik
        【解决方案6】:

        使用 Swift 3 或 4 您可以访问这些 http 请求进行服务器通信。

        // 用于请求 POST 数据

         func postAction()  {
        //declare parameter as a dictionary which contains string as key and value combination. considering inputs are valid
        let parameters = ["id": 13, "name": "jack"] as [String : Any]
        //create the url with URL
        let url = URL(string: "www.requestURL.php")! //change the url
        //create the session object
        let session = URLSession.shared
        //now create the URLRequest object using the url object
        var request = URLRequest(url: url)
        request.httpMethod = "POST" //set http method as POST
        do {
            request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted) // pass dictionary to nsdata object and set it as request body
        } catch let error {
            print(error.localizedDescription)
        }
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("application/json", forHTTPHeaderField: "Accept")
        //create dataTask using the session object to send data to the server
        let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
            guard error == nil else {
                return
            }
            guard let data = data else {
                return
            }
            do {
                //create json object from data
                if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
                    print(json)
                    // handle json...
                }
            } catch let error {
                print(error.localizedDescription)
            }
        })
        task.resume() }
        

        // 用于从请求中获取数据

        func GetRequest()  {
            let urlString = URL(string: "http://www.requestURL.php") //change the url
        
            if let url = urlString {
                let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
                    if error != nil {
                        print(error ?? "")
                    } else {
                        if let responceData = data {
                            print(responceData) //JSONSerialization
                            do {
                                //create json object from data
                                if let json = try JSONSerialization.jsonObject(with:responceData, options: .mutableContainers) as? [String: Any] {
                                    print(json)
                                    // handle json...
                                }
                            } catch let error {
                                print(error.localizedDescription)
                            }
                        }
                    }
                }
                task.resume()
            }
        }
        

        // 用于从请求中获取图片或视频等下载内容

        func downloadTask()  {
            // Create destination URL
            let documentsUrl:URL =  FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first as URL!
            let destinationFileUrl = documentsUrl.appendingPathComponent("downloadedFile.jpg")
            //Create URL to the source file you want to download
            let fileURL = URL(string: "http://placehold.it/120x120&text=image1")
            let sessionConfig = URLSessionConfiguration.default
            let session = URLSession(configuration: sessionConfig)
            let request = URLRequest(url:fileURL!)
        
            let task = session.downloadTask(with: request) { (tempLocalUrl, response, error) in
                if let tempLocalUrl = tempLocalUrl, error == nil {
                    // Success
                    if let statusCode = (response as? HTTPURLResponse)?.statusCode {
                        print("Successfully downloaded. Status code: \(statusCode)")
                    }
        
                    do {
                        try FileManager.default.copyItem(at: tempLocalUrl, to: destinationFileUrl)
                    } catch (let writeError) {
                        print("Error creating a file \(destinationFileUrl) : \(writeError)")
                    }
        
                } else {
                    print("Error took place while downloading a file. Error description: %@", error?.localizedDescription ?? "");
                }
            }
            task.resume()
        
        }
        

        【讨论】:

          【解决方案7】:

          目标 C

          使用参数发布 API 并使用 url 验证以导航是否为 json
          状态为“成功”的响应键

          NSString *string= [NSString stringWithFormat:@"url?uname=%@&pass=%@&uname_submit=Login",self.txtUsername.text,self.txtPassword.text];
              NSLog(@"%@",string);
              NSURL *url = [NSURL URLWithString:string];
              NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
              [request setHTTPMethod:@"POST"];
              NSURLResponse *response;
              NSError *err;
              NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
              NSLog(@"responseData: %@", responseData);
              NSString *str = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
              NSLog(@"responseData: %@", str);
                  NSDictionary* json = [NSJSONSerialization JSONObjectWithData:responseData
                                                                   options:kNilOptions
                                                                     error:nil];
              NSDictionary* latestLoans = [json objectForKey:@"status"];
              NSString *str2=[NSString stringWithFormat:@"%@", latestLoans];
              NSString *str3=@"success";
              if ([str3 isEqualToString:str2 ])
              {
                  [self performSegueWithIdentifier:@"move" sender:nil];
                  NSLog(@"successfully.");
              }
              else
              {
                  UIAlertController *alert= [UIAlertController
                                           alertControllerWithTitle:@"Try Again"
                                           message:@"Username or Password is Incorrect."
                                           preferredStyle:UIAlertControllerStyleAlert];
                  UIAlertAction* ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault
                                                             handler:^(UIAlertAction * action){
                                                                 [self.view endEditing:YES];
                                                             }
                                       ];
                  [alert addAction:ok];
                  [[UIView appearanceWhenContainedIn:[UIAlertController class], nil] setTintColor:[UIColor redColor]];
                  [self presentViewController:alert animated:YES completion:nil];
                  [self.view endEditing:YES];
                }
          

          JSON 响应 : {"status":"success","user_id":"58","user_name":"dilip","re​​sult":"您已成功登录" } 工作代码

          **

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-02-27
            • 1970-01-01
            • 2011-03-20
            • 2013-11-13
            相关资源
            最近更新 更多