Senden einer HTTP-POST-Anfrage unter iOS

86

Ich versuche, einen HTTP-Beitrag mit der von mir entwickelten iOS-Anwendung zu senden, aber der Push erreicht den Server nie, obwohl ich als Antwort einen Code 200 erhalte (von der URL-Verbindung). Ich bekomme nie eine Antwort vom Server und der Server erkennt meine Beiträge nicht (der Server erkennt Beiträge von Android).

Ich benutze ARC, habe aber pd und urlConnection als stark eingestellt.

Dies ist mein Code zum Senden der Anfrage

 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];

Dies ist mein Code für den Delegierten

#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

Die Konsole druckt immer die folgenden Zeilen und nur die folgenden Zeilen:

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 <>
Daan Luttik
quelle

Antworten:

188

Der folgende Code beschreibt ein einfaches Beispiel mit einer POSTMethode. ( Wie kann man Daten nach POSTMethode übergeben? )

Hier beschreibe ich, wie man die POST-Methode verwenden kann.

1. Legen Sie die Post-Zeichenfolge mit dem tatsächlichen Benutzernamen und Passwort fest.

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

2. Codieren Sie die Post-Zeichenfolge mit NSASCIIStringEncodingund auch die Post-Zeichenfolge, die Sie im NSData-Format senden müssen.

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

Sie müssen die tatsächliche Länge Ihrer Daten senden. Berechnen Sie die Länge der Post-Zeichenfolge.

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

3. Erstellen Sie eine Urlrequest mit allen Eigenschaften wie HTTPMethode, http-Headerfeld und Länge der Post-Zeichenfolge. URLRequestObjekt erstellen und initialisieren.

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

Legen Sie die URL fest, für die Sie die Daten an diese Anforderung senden möchten.

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

Stellen Sie nun die HTTP- Methode ( POST oder GET ) ein. Schreiben Sie diese Zeilen so, wie sie in Ihrem Code stehen.

[request setHTTPMethod:@"POST"]; 

Stellen Sie das HTTPHeader-Feld mit der Länge der Post-Daten ein.

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

Legen Sie auch den codierten Wert für das HTTP-Headerfeld fest.

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

Stellen Sie die HTTPBodyvon der URLRequest mit postdata.

[request setHTTPBody:postData];

4. Erstellen Sie nun das URLConnection-Objekt. Initialisieren Sie es mit der URLRequest.

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

Es gibt die initialisierte URL-Verbindung zurück und beginnt, die Daten für die URL-Anforderung zu laden. Sie können überprüfen, ob Ihre URLVerbindung ordnungsgemäß hergestellt wurde oder nicht, indem Sie die folgende if / else- Anweisung verwenden.

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

5. Um die Daten von der HTTP-Anforderung zu erhalten, können Sie die in der URLConnection-Klassenreferenz bereitgestellten Delegierungsmethoden verwenden. Die Delegierungsmethoden sind wie folgt.

// 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

Informationen zur Methode finden Sie auch in dieser und dieser DokumentationPOST .

Und hier ist das beste Beispiel mit dem Quellcode der HTTPPost-Methode.

iPatel
quelle
1
Überprüfen Sie auch, ob kein Caching stattfindet. Das würde erklären, warum Sie eine '200' haben, ohne dass etwas auf dem Server passiert.
Jelle
Überprüfen Sie die akzeptierte Antwort von stackoverflow.com/questions/405151/… und / oder Google auf "nsurlconnection cache policy"
Jelle
1
Obwohl die Antwort so oft akzeptiert wurde, weist der in dieser Antwort angegebene Code eine Reihe eklatanter Probleme auf und wird in der Praxis problematisch sein.
CouchDeveloper
1
@iPatel Aber können wir Bilddaten mit dem oben angegebenen Post-Methodencode senden?
iHulk
1
Leider ist dieser Code falsch und anfällig für Injektionsangriffe. Wenn der Benutzer zufällig ein "&" im Kennwort hat, werden alle weiteren Zeichen als zusätzlicher POST-Parameter analysiert. Eine absichtliche Manipulation ist möglich.
Ge0rg
4
-(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];
}
Mannam Brahmam
quelle
2

Ich bin mir nicht sicher warum, aber sobald ich die folgende Methode auskommentiere, funktioniert es:

connectionDidFinishDownloading:destinationURL:

Außerdem glaube ich nicht, dass Sie die Methoden aus dem NSUrlConnectionDownloadDelegate-Protokoll benötigen, sondern nur die aus NSURLConnectionDataDelegate, es sei denn, Sie möchten einige Download-Informationen.

Nickygerritsen
quelle
Ich möchte die Download-Informationen, deshalb habe ich die Funktion connectionDidFinishDownloading: destinationURL:
Daan Luttik
1
Anscheinend funktioniert NSURLConnectionDownloadDelegate nur in Zeitungskiosk-Apps .... Zumindest sagt das dieser Thread: stackoverflow.com/questions/6735121/…
nickygerritsen
2

Hier ist die Methode, die ich in meiner Protokollierungsbibliothek verwendet habe: https://github.com/goktugyil/QorumLogs

Diese Methode füllt HTML-Formulare in Google Forms aus. Hoffe, es hilft jemandem, der Swift benutzt.

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)
Esqarrouth
quelle
1

Senden einer HTTP-POST-Anfrage unter iOS (Ziel 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];
}
Ronny Morán
quelle
Dies ist neu ... Antworten 4 Jahre nach dem
Absenden
Diese "Postexample" -Funktion ist schneller als die Antwort : p @DaanLuttik
Ronny Morán
1

Mit Swift 3 oder 4 können Sie auf diese http-Anforderung für eine getrennte Kommunikation zugreifen.

// POST-Daten anfordern

 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() }

// Um ​​die Daten von der Anfrage zu erhalten

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()
    }
}

// Um ​​den Download-Inhalt wie Bild oder Video von der Anfrage zu erhalten

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()

}
Technik
quelle
1

Ziel c

Veröffentlichen Sie die API mit Parametern und validieren Sie sie mit der URL, um zu navigieren, ob der JSON-
Antwortschlüssel den Status "Erfolg" hat.

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-Antwort : {"status": "success", "user_id": "58", "user_name": "dilip", "result": "Sie wurden erfolgreich angemeldet"} Arbeitscode

** **.

Dilip Tiwari
quelle