Aktualizacja: Znaleziono rozwiązanie. Możesz to przeczytać na końcu postu.
Próbuję wykonać żądanie POST do zdalnego interfejsu API REST przy użyciu NSURLSession
. Chodzi o złożenie wniosku z dwoma parametrami: deviceId
i textContent
.
Problem polega na tym, że te parametry nie są rozpoznawane przez serwer. Część serwerowa działa poprawnie, ponieważ wysłałem POST za pomocą POSTMAN dla Google Chrome i działało idealnie.
Oto kod, którego teraz używam:
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];
Próbowałem tej samej procedury z 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];
Jakieś pomysły?
Rozwiązanie
Problem z moim podejściem polegał na tym, że wysyłałem niepoprawny Content-Type
nagłówek ze wszystkimi swoimi żądaniami. Tak więc jedyną zmianą potrzebną do poprawnego działania kodu jest usunięcie Content-Type = application/json
nagłówka HTTP. Prawidłowy kod to:
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];
Wysyłanie zdjęć wraz z innymi parametrami
Jeśli chcesz opublikować zdjęcia wraz z innymi parametrami za pomocą NSURLSession
tutaj, masz przykład:
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];
źródło
NSURLSessionUploadTask
, wysyła surowe dane na twój serwer. Nadal możesz pracować - na przykład za pośrednictwemfile_get_contents('php://input') in PHP
- ale musisz dołączyć inne dane do nagłówków.Content-Type
wszystkiego była wszystkim, czego potrzebowałem, aby to rozgryźć. Dzięki!Odpowiedzi:
Możesz spróbować użyć NSDictionary dla parametrów. Poniższe parametry wyślą parametry poprawnie do serwera JSON.
Mam nadzieję, że to pomaga (próbuję rozwiązać problem z autentycznością CSRF z powyższym - ale wysyła parametry w NSDictionary).
źródło
NSJSONSerialization
) i dodałem kod do publikowania zdjęć wraz z innymi parametrami. Zaktualizowałem oryginalny post. Dziękujemy za pomoc :-)Motywacja
Czasami dostaję błędy, kiedy chcesz przekazać szeregowane httpBody
Data
zDictionary
, co w większości przypadków jest spowodowane niewłaściwym kodowaniem lub zniekształconymi danymi z powodu obiektów niezgodnych z NSCoding w plikuDictionary
.Rozwiązanie
W zależności od wymagań jednym łatwym rozwiązaniem byłoby utworzenie
String
zamiastDictionary
i przekonwertowanie goData
. Poniżej znajdują się próbki kodu napisane naObjective-C
iSwift 3.0
.Cel C
Szybki
źródło
url
, tomethod
wtedybody
tak, to musi być zmienny? A jeśli tak jest, to gdzie kiedykolwiek trzeba by użyćNSURLRequest
?Możesz użyć https://github.com/mxcl/OMGHTTPURLRQ
źródło
Rozwiązanie Swift 2.0 jest tutaj:
źródło
Jeśli używasz Swift, biblioteka Just zrobi to za Ciebie. Przykład z pliku readme:
źródło
Zmieniono kod Teji Kumar Bethiny dla Swift 3:
źródło
źródło
-[NSUserDefaults synchronize]
. Z dokumentacji Apple'a „ta metoda jest niepotrzebna i nie powinna być stosowana”.