Mise à jour: solution trouvée. Vous pouvez le lire à la fin de l'article.
J'essaie d'exécuter une requête POST vers une API REST distante à l'aide de NSURLSession
. L'idée est de faire une demande avec deux paramètres: deviceId
et textContent
.
Le problème est que ces paramètres ne sont pas reconnus par le serveur. La partie serveur fonctionne correctement car j'ai envoyé un POST en utilisant POSTMAN pour Google Chrome et cela a parfaitement fonctionné.
Voici le code que j'utilise en ce moment:
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 était que j'envoyais l'en- Content-Type
tête incorrect avec toutes mes demandes. La seule modification nécessaire pour que le code fonctionne correctement consiste donc à supprimer l' Content-Type = application/json
en-tête HTTP. Donc, le bon code serait le suivant:
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];
Envoi d'images avec d'autres paramètres
Si vous devez publier des images avec d'autres paramètres en utilisant 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];
la source
NSURLSessionUploadTask
, il publie des données brutes sur votre serveur. Avec lequel vous pouvez toujours travailler - par exemple, viafile_get_contents('php://input') in PHP
- mais vous devez inclure d'autres données dans les en-têtes.Content-Type
était tout ce dont j'avais besoin pour comprendre les choses. Merci!Réponses:
Vous pouvez essayer d'utiliser un NSDictionary pour les params. Ce qui suit enverra les paramètres correctement à un serveur JSON.
J'espère que cela aide (j'essaie de trier un problème d'authenticité CSRF avec ce qui précède - mais cela envoie les paramètres dans le NSDictionary).
la source
NSJSONSerialization
) et j'ai ajouté le code pour publier des images avec d'autres paramètres. J'ai mis à jour le message d'origine. Merci pour votre aide :-)Motivation
Parfois, je reçois des erreurs lorsque vous souhaitez transmettre httpBody sérialisé à
Data
deDictionary
, ce qui est dans la plupart des cas dû au mauvais codage ou à des données malformées en raison d' objets non conformes au NSCoding dans leDictionary
.Solution
En fonction de vos besoins une solution facile serait de créer un
String
lieu deDictionary
et le convertir enData
. Vous avez les exemples de code ci-dessous écritsObjective-C
etSwift 3.0
.Objectif c
Rapide
la source
url
, puismethod
alorsbody
il doit être mutable? Et si tel est le cas, où auriez-vous besoin de l'utiliserNSURLRequest
?Vous pouvez utiliser https://github.com/mxcl/OMGHTTPURLRQ
la source
La solution Swift 2.0 est là:
la source
Si vous utilisez Swift, la bibliothèque Just le fait pour vous. Exemple à partir de son fichier readme:
la source
Le code de Teja Kumar Bethina a changé pour Swift 3:
la source
la source
-[NSUserDefaults synchronize]
. D'après la documentation d'Apple, "cette méthode est inutile et ne doit pas être utilisée".