225 votes

Envoyer la requête POST à l’aide de NSURLSession

Mise à jour: Solution trouvée. Vous pouvez le lire à la fin du post.

Je suis en train d'effectuer une requête POST à distance à l'aide de l'API REST NSURLSession. L'idée est de faire une demande auprès de deux paramètres: deviceId et textContent.

Le problème est que ces paramètres ne sont pas reconnu par le serveur. La partie serveur fonctionne correctement, car j'ai envoyé un courrier en utilisant le FACTEUR de Google Chrome et cela a fonctionné parfaitement.

C'est le code que j'utilise actuellement:

NSString *deviceID = [[NSUserDefaults standardUserDefaults] objectForKey:@"deviceID"];
NSString *textContent = @"New note";
NSString *noteDataString = [NSString stringWithFormat:@"deviceId=%@&textContent=%@", deviceID, textContent];

NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfiguration.HTTPAdditionalHeaders = @{
                                               @"api-key"       : @"API_KEY",
                                               @"Content-Type"  : @"application/json"
                                               };
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
NSURL *url = [NSURL URLWithString:@"http://url_to_manage_post_requests"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPBody = [noteDataString dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPMethod = @"POST";
NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    // The server answers with an error because it doesn't receive the params
}];
[postDataTask resume];

J'ai essayé la même procédure avec un NSURLSessionUploadTask:

// ...
NSURL *url = [NSURL URLWithString:@"http://url_to_manage_post_requests"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:[noteDataString dataUsingEncoding:NSUTF8StringEncoding] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    // The server answers with an error because it doesn't receive the params
}];
[uploadTask resume];

Des idées?

Solution

Le problème avec mon approche est que j'ai été l'envoi de la incorrectes Content-Type - tête avec toutes mes demandes. Donc, le seul changement nécessaire pour que le code fonctionne correctement est de supprimer l' Content-Type = application/json - tête HTTP. Donc le bon code serait celui-ci:

NSString *deviceID = [[NSUserDefaults standardUserDefaults] objectForKey:@"deviceID"];
NSString *textContent = @"New note";
NSString *noteDataString = [NSString stringWithFormat:@"deviceId=%@&textContent=%@", deviceID, textContent];

NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfiguration.HTTPAdditionalHeaders = @{
                                               @"api-key"       : @"API_KEY"
                                               };
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
NSURL *url = [NSURL URLWithString:@"http://url_to_manage_post_requests"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPBody = [noteDataString dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPMethod = @"POST";
NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    // The server answers with an error because it doesn't receive the params
}];
[postDataTask resume];

L'envoi d'images avec d'autres paramètres

Si vous avez besoin d'afficher des images avec d'autres paramètres à l'aide de NSURLSession ici vous avez un exemple:

NSString *deviceID = [[NSUserDefaults standardUserDefaults] objectForKey:@"deviceID"];
NSString *textContent = @"This is a new note";

// Build the request body
NSString *boundary = @"SportuondoFormBoundary";
NSMutableData *body = [NSMutableData data];
// Body part for "deviceId" parameter. This is a string.
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", @"deviceId"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"%@\r\n", deviceID] dataUsingEncoding:NSUTF8StringEncoding]];
// Body part for "textContent" parameter. This is a string.
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", @"textContent"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"%@\r\n", textContent] dataUsingEncoding:NSUTF8StringEncoding]];
// Body part for the attachament. This is an image.
NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:@"ranking"], 0.6);
if (imageData) {
    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"image.jpg\"\r\n", @"image"] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[@"Content-Type: image/jpeg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:imageData];
    [body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
}
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];

// Setup the session
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfiguration.HTTPAdditionalHeaders = @{
                                               @"api-key"       : @"55e76dc4bbae25b066cb",
                                               @"Accept"        : @"application/json",
                                               @"Content-Type"  : [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary]
                                               };

// Create the session
// We can use the delegate to track upload progress
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:nil];

// Data uploading task. We could use NSURLSessionUploadTask instead of NSURLSessionDataTask if we needed to support uploads in the background
NSURL *url = [NSURL URLWithString:@"URL_TO_UPLOAD_TO"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
request.HTTPBody = body;
NSURLSessionDataTask *uploadTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    // Process the response
}];
[uploadTask resume];

170voto

greentor Points 730

Vous pouvez essayer d’utiliser un NSDictionary pour les params. Le texte suivant enverra les paramètres correctement sur un serveur JSON.

Espérons que cette aide (je suis en train de régler un problème d’authenticité CSRF avec ce qui précède - mais il envoie les params dans le NSDictionary).

8voto

mxcl Points 5921

0voto

david72 Points 41

Pour qui utilise l’URL du formulaire, cela fonctionne pour moi:

 NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@/%@/", apiURL, command]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
                                                           cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                       timeoutInterval:1.0];

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

request.HTTPBody    = [postString dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPMethod  = @"POST";

NSURLSession *session = [NSURLSession sharedSession];

NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

    NSString* newStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"result string: %@", newStr);

    NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
    NSLog(@"result json: %@", jsonArray);

}];

[postDataTask resume];
 

Notez que l'URL doit se terminer par /

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X