Обновление: решение найдено. Вы можете прочитать это в конце поста.
Я пытаюсь выполнить запрос POST к удаленному API REST с помощью NSURLSession
. Идея состоит в том, чтобы сделать запрос с двумя параметрами: deviceId
и textContent
.
Проблема в том, что эти параметры не распознаются сервером. Серверная часть работает правильно, потому что я отправил POST, используя POSTMAN для Google Chrome, и он работал отлично.
Вот код, который я сейчас использую:
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];
Я пробовал ту же процедуру с 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];
Любые идеи?
Решение
Проблема с моим подходом заключалась в том, что я отправлял неправильный Content-Type
заголовок со всеми своими запросами. Таким образом, единственное изменение, необходимое для правильной работы кода - это удалить Content-Type = application/json
заголовок HTTP. Таким образом, правильный код будет следующим:
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];
Отправка изображений вместе с другими параметрами
Если вам нужно опубликовать изображения вместе с другими параметрами, используя NSURLSession
здесь, у вас есть пример:
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];
источник
NSURLSessionUploadTask
, он отправляет необработанные данные на ваш сервер. С которым вы все еще можете работать - например, черезfile_get_contents('php://input') in PHP
- но вы должны включить другие данные в заголовки.Content-Type
все, что мне было нужно, чтобы выяснить это, было наводить на размышления. Спасибо!Ответы:
Вы можете попробовать использовать NSDictionary для параметров. Следующее правильно отправит параметры на сервер JSON.
Надеюсь, что это поможет (я пытаюсь решить проблему подлинности CSRF с вышеупомянутым - но он отправляет параметры в NSDictionary).
источник
NSJSONSerialization
), и я добавил код для публикации изображений вместе с другими параметрами. Я обновил оригинальный пост. Спасибо за вашу помощь :-)мотивация
Иногда я получаю некоторые ошибки, когда вы хотите передать httpBody serialized to
Data
fromDictionary
, что в большинстве случаев происходит из-за неправильного кодирования или искаженных данных из-за не соответствующих NSCoding объектов вDictionary
.Решение
В зависимости от ваших требований, одним из простых решений было бы создать
String
вместоDictionary
и преобразовать его вData
. У вас есть примеры кода ниже, написанные наObjective-C
иSwift 3.0
.Objective-C
стриж
источник
url
,method
тогда,body
значит, оно должно быть изменчивым? И если это так, то где когда-либо нужно использоватьNSURLRequest
?Вы можете использовать https://github.com/mxcl/OMGHTTPURLRQ
источник
Решение Swift 2.0 находится здесь:
источник
Если вы используете Swift, библиотека Just сделает это за вас. Пример из файла readme:
источник
Код Теджи Кумара Бетины изменен для Swift 3:
источник
источник
-[NSUserDefaults synchronize]
. Из документации Apple «этот метод не нужен и не должен использоваться».