2015-12-06 4 views
3

POST с AFNetworking:Replicate AFNetworking POST с запросом NSURLSession

let urlString = "http://example.com/file.php" 
let dictionary = ["key1": [1,2,3], "key2": [2,4,6]] 

var error: NSError? 
let data = NSJSONSerialization.dataWithJSONObject(dictionary, options: NSJSONWritingOptions.allZeros, error: &error) 
let jsonString = NSString(data: data!, encoding: NSUTF8StringEncoding) 
let parameters = ["data" : jsonString!] 

let manager = AFHTTPSessionManager() 
manager.responseSerializer = AFHTTPResponseSerializer() 
manager.POST(urlString, parameters: parameters, success: 
    { 
     requestOperation, response in 

     let result = NSString(data: response as! NSData, encoding: NSUTF8StringEncoding)! 

     println(result) 
    }, 
    failure: 
    { 
     requestOperation, error in 
}) 

запрос POST с NSURLSession:

let request = NSMutableURLRequest(URL: NSURL(string: urlString)!) 
request.HTTPMethod = "POST" 

let bodyData = NSJSONSerialization.dataWithJSONObject(parameters, options: NSJSONWritingOptions.allZeros, error: &error)! 
request.HTTPBody = bodyData 
request.addValue("application/json", forHTTPHeaderField: "Content-Type") 
request.addValue("\(bodyData.length)", forHTTPHeaderField: "Content-Length") 

NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in 
    let result = NSString(data: data, encoding: NSUTF8StringEncoding)! 

    println(result) 
}).resume() 

На сервере у меня есть:

$data = json_decode($_POST["data"], true); 
if (!$data) { 
    echo "Error: Invalid POST data"; 
    return; 
} 
//do some stuff 

echo "success"; 

На втором случае я получаю «Ошибка: неверные данные POST». Что я делаю неправильно?

+0

попробуйте добавить это: request.addValue ("приложения/JSON", forHTTPHeaderField: "Принять") –

+1

@DanBe aulieu Вы сделали бы это, если бы запрос хотел сообщить серверу, что он примет ответ JSON. Но ответ здесь не проблема. Проблема заключается в запросе. – Rob

+0

@rob спасибо за освобождение. Я недавно обманывал Alamofire, поэтому я новичок в NSUrl. –

ответ

5

Это потому, что пример AFNetworking не создает запрос JSON, тогда как ваш пример NSURLSession. Пример AFNetworking создает запрос application/x-www-form-urlencoded (где значение представляет собой строку JSON, которую вы создали вручную). Вы можете либо изменить код сервера, чтобы принять запросы JSON, либо изменить запрос на запрос application/x-www-form-urlencoded.


Если вы посмотрите на тело запроса AFNetworking в чем-то вроде Charles, вы можете увидеть это создает что-то вроде:

data=%7B%22key1%22%3A%5B1%2C2%2C3%5D%2C%22key3%22%3A%5B%22Harold%20%26%20Maude%22%5D%2C%22key2%22%3A%5B2%2C4%2C6%5D%7D 

Если вы отмените процентов, спасаясь от значения, связанного с data, что это эффективно

data={"key1":[1,2,3],"key3":["Harold & Maude"],"key2":[2,4,6]} 

(Обратите внимание, что я добавил key3, чтобы показать, что процент экранирование побега стандарт защищены . символы, а также & и + тоже)

Если вы хотите сделать это самостоятельно с NSURLSession, вы должны строить, что и тогда процент денется, как так:

let allowed = NSCharacterSet.alphanumericCharacterSet().mutableCopy() as! NSMutableCharacterSet 
allowed.addCharactersInString("-._~") 
let bodyString = "data=" + jsonString.stringByAddingPercentEncodingWithAllowedCharacters(allowed)! 

Честно говоря, это довольно странный подход, встраивание JSON в запрос application/x-www-form-urlencoded. Я бы просто изменить сервер, чтобы принять стандартный запрос JSON (обходя $_POST переменные в целом):

$handle = fopen("php://input", "rb"); 
$raw_post_data = ''; 
while (!feof($handle)) { 
    $raw_post_data .= fread($handle, 8192); 
} 
fclose($handle); 

$body = json_decode($raw_post_data, true); 

Кстати, после того, как код сервера принимает запрос чистого JSON, Свифт код клиента 1.x будет:

let request = NSMutableURLRequest(URL: NSURL(string: urlString)!) 
request.HTTPMethod = "POST" 

request.HTTPBody = NSJSONSerialization.dataWithJSONObject(parameters, options: NSJSONWritingOptions.allZeros, error: &error)! 
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") 

NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in 
    let result = NSString(data: data, encoding: NSUTF8StringEncoding)! 

    println(result) 
}).resume() 

AFNetworking эквивалент будет выглядеть так:

let urlString = "http://example.com/file.php" 
let dictionary = ["key1": [1,2,3], "key2": [2,4,6]] 

let manager = AFHTTPSessionManager() 
manager.requestSerializer = AFJSONRequestSerializer() 
manager.responseSerializer = AFHTTPResponseSerializer() 
manager.POST(urlString, parameters: parameters, success: 
    { 
     requestOperation, response in 

     let result = NSString(data: response as! NSData, encoding: NSUTF8StringEncoding)! 

     println(result) 
    }, 
    failure: 
    { 
     requestOperation, error in 
}) 
Смежные вопросы