Envoi d'une 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 mauvaise Content-Type
- tête avec toutes mes demandes. Donc, le seul changement nécessaire pour que le code fonctionne correctement est de supprimer la Content-Type = application/json
en-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];
D'envoyer des 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];
- Tangentiellement, si vous utilisez seulement un
NSURLSessionUploadTask
, il publie des données brutes de votre serveur. Qui, vous pouvez toujours travailler avec, par exemple, viafile_get_contents('php://input') in PHP
-- mais vous devez inclure d'autres données dans les en-têtes. - Belle solution! Utilisé pour créer mon propre formulaire multipart compositeur.
- J'avais une autre question, mais le tip-off concernant
Content-Type
était tout ce que j'avais besoin de comprendre les choses. Merci! - Pour certaines raisons, ça a arrêté de travailler pour moi, tout d'un coup sur la dernière version ios8. Il a travaillé comme un champion pour un an, puis tout d'un coup je reçois des requêtes mal formées sur le serveur et je ne suis pas sûr de ce changement dans la façon dont je compose à la demande. Je ne pouvais pas reproduire le problème, les utilisateurs avaient avec XCode simulateur, puis j'ai mis à jour de XCode 6.3.1 et kablam je suis vissé juste en train de me tuer. Impossible de savoir pourquoi mon serveur est tellement malheureux avec les demandes.
- Merci de donner la réponse avec le code pour l'envoi d'une image avec des paramètres. L'envoi de l'image a fonctionné à merveille! Comme pour les paramètres, j'ai dû ajouter à l'URL de leur faire le travail.
- Je suis votre exemple, et pour envoyer de multiples champs de l'image. Je vous envoie le format d'image PNG. En cours d'exécution dans un problème, merci de m'aider à le résoudre. J'ai un django basée sur serveur et renvoie une erreur pour l'image. "Les données présentées n'était pas un fichier. Vérifiez le type de codage sur la forme."
- [corps appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n", @"image_file"] dataUsingEncoding:NSUTF8StringEncoding]]; [corps appendData:[@"Content-Type: image/png\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [corps appendData:pageData]; [corps appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
- une boucle de commande comme ci-dessous travail "curl-i-F "page_index=0" -F "p=1" -F "image_file=@./FullSizeRender.png gmm.com:5000/p/images HTTP/1.1"
- votre solution, y compris l'API était EXACTEMENT ce que je cherchais, merci beaucoup!!!!
- La "solution" à la question devrait être ajouté comme une réponse 🙂
- est-il nécessaire d'ajouter des en-têtes supplémentaires ?
- Ajout de toutes les chaînes et seulement la conversion de données lorsque la chaîne est composée également de travail, tout en le rendant un peu plus lisible 🙂
- S'il vous plaît ne mettez pas de réponses à votre question, si vous avez un poste à titre de réponse, plutôt que de le mettre là. Veuillez vous référer à cette la poste sur Meta
Vous devez vous connecter pour publier un commentaire.
Vous pouvez essayer d'utiliser un NSDictionary pour les paramètres. Le suivant va envoyer correctement les paramètres d'un JSON serveur.
Espérons que cette aide (je suis en train de trier une CSRF l'authenticité d'un problème avec l'au-dessus - mais il n'envoyer les paramètres dans le NSDictionary).
NSJSONSerialization
) et j'ai ajouté le code pour afficher des images avec d'autres paramètres. J'ai mis à jour le post original. Merci pour votre aide 🙂Motivation
Parfois, j'ai été faire des erreurs lorsque vous souhaitez passer httpBody sérialisé à
Data
deDictionary
, qui dans la plupart des cas est due à un mauvais encodage ou à des données incorrectes en raison de la non NSCoding conforme objets dans leDictionary
.Solution
Selon vos besoins, une solution simple serait de créer un
String
au lieu deDictionary
et la convertir enData
. Vous avez les exemples de code ci-dessous écrit surObjective-C
etSwift 3.0
.Objective-C
Swift
url
, puismethod
puisbody
donc il doit être muable? Et si c'est le cas alors, où serait jamais besoin d'utiliserNSURLRequest
?Vous pouvez utiliser https://github.com/mxcl/OMGHTTPURLRQ
Swift 2.0 solution est ici:
Si vous êtes en utilisant Swift, la Juste bibliothèque fait pour vous. Exemple de fichier lisez-moi:
Teja Kumar Bethina du code modifié pour Swift 3:
-[NSUserDefaults synchronize]
. À partir de la documentation d'Apple "cette méthode n'est pas nécessaire et ne doit pas être utilisé."