使用NSURLSession发送POST请求

更新:find解决scheme。 你可以在post结尾阅读。

我正在尝试使用NSURLSession向远程REST API执行POST请求。 这个想法是用两个参数: deviceIdtextContent进行请求。

问题是这些参数不被服务器识别。 服务器部分正常工作,因为我已经使用POSTMAN发送了一个POST的谷歌浏览器,它的工作完美。

这是我现在使用的代码:

 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]; 

你可以尝试使用NSDictionary的参数。 以下将正确地将参数发送到JSON服务器。

 NSError *error; NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil]; NSURL *url = [NSURL URLWithString:@"[JSON SERVER"]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; [request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request addValue:@"application/json" forHTTPHeaderField:@"Accept"]; [request setHTTPMethod:@"POST"]; NSDictionary *mapData = [[NSDictionary alloc] initWithObjectsAndKeys: @"TEST IOS", @"name", @"IOS TYPE", @"typemap", nil]; NSData *postData = [NSJSONSerialization dataWithJSONObject:mapData options:0 error:&error]; [request setHTTPBody:postData]; NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { }]; [postDataTask resume]; 

希望这有助于(我试图sortingCSRF真实性问题与上述 – 但它确实在NSDictionary发送参数)。

动机

有时候我想要把httpBody序列化到Dictionary Data时,会出现一些错误,在大多数情况下,这是由于Dictionary中的非NSCoding兼容对象导致编码错误或数据格式错误。

根据您的要求,一个简单的解决scheme将创build一个String而不是Dictionary ,并将其转换为Data 。 你有下面的代码示例写在Objective-CSwift 3.0

Objective-C的

 // Create the URLSession on the default configuration NSURLSessionConfiguration *defaultSessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultSessionConfiguration]; // Setup the request with URL NSURL *url = [NSURL URLWithString:@"yourURL"]; NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url]; // Convert POST string parameters to data using UTF8 Encoding NSString *postParams = @"api_key=APIKEY&email=example@example.com&password=password"; NSData *postData = [postParams dataUsingEncoding:NSUTF8StringEncoding]; // Convert POST string parameters to data using UTF8 Encoding [urlRequest setHTTPMethod:@"POST"]; [urlRequest setHTTPBody:postData]; // Create dataTask NSURLSessionDataTask *dataTask = [defaultSession dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { // Handle your response here }]; // Fire the request [dataTask resume]; 

迅速

 // Create the URLSession on the default configuration let defaultSessionConfiguration = URLSessionConfiguration.default let defaultSession = URLSession(configuration: defaultSessionConfiguration) // Setup the request with URL let url = URL(string: "yourURL") var urlRequest = URLRequest(url: url!) // Note: This is a demo, that's why I use implicitly unwrapped optional // Convert POST string parameters to data using UTF8 Encoding let postParams = "api_key=APIKEY&email=example@example.com&password=password" let postData = postParams.data(using: .utf8) // Set the httpMethod and assign httpBody urlRequest.httpMethod = "POST" urlRequest.httpBody = postData // Create dataTask let dataTask = defaultSession.dataTask(with: urlRequest) { (data, response, error) in // Handle your response here } // Fire the request dataTask.resume() 

你可以使用https://github.com/mxcl/OMGHTTPURLRQ

 id config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:someID]; id session = [NSURLSession sessionWithConfiguration:config delegate:someObject delegateQueue:[NSOperationQueue new]]; OMGMultipartFormData *multipartFormData = [OMGMultipartFormData new]; [multipartFormData addFile:data1 parameterName:@"file1" filename:@"myimage1.png" contentType:@"image/png"]; NSURLRequest *rq = [OMGHTTPURLRQ POST:url:multipartFormData]; id path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"upload.NSData"]; [rq.HTTPBody writeToFile:path atomically:YES]; [[session uploadTaskWithRequest:rq fromFile:[NSURL fileURLWithPath:path]] resume]; 

如果你正在使用Swift, Just库会为你做这个。 来自自述文件的示例:

 // talk to registration end point Just.post( "http://justiceleauge.org/member/register", data: ["username": "barryallen", "password":"ReverseF1ashSucks"], files: ["profile_photo": .URL(fileURLWithPath:"flash.jpeg", nil)] ) { (r) if (r.ok) { /* success! */ } } 

Swift 2.0解决scheme在这里:

  let urlStr = “http://url_to_manage_post_requests” let url = NSURL(string: urlStr) let request: NSMutableURLRequest = NSMutableURLRequest(URL: url!) request.HTTPMethod = "POST" request.setValue(“application/json” forHTTPHeaderField:”Content-Type”) request.timeoutInterval = 60.0 //additional headers request.setValue(“deviceIDValue”, forHTTPHeaderField:”DeviceId”) let bodyStr = “string or data to add to body of request” let bodyData = bodyStr.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true) request.HTTPBody = bodyData let session = NSURLSession.sharedSession() let task = session.dataTaskWithRequest(request){ (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in if let httpResponse = response as? NSHTTPURLResponse { print("responseCode \(httpResponse.statusCode)") } if error != nil { // You can handle error response here print("\(error)") }else { //Converting response to collection formate (array or dictionary) do{ let jsonResult: AnyObject = (try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)) //success code }catch{ //failure code } } } task.resume() 

Teja Kumar Bethina的代码因Swift 3而改变:

  let urlStr = "http://url_to_manage_post_requests" let url = URL(string: urlStr) var request: URLRequest = URLRequest(url: url!) request.httpMethod = "POST" request.setValue("application/json", forHTTPHeaderField:"Content-Type") request.timeoutInterval = 60.0 //additional headers request.setValue("deviceIDValue", forHTTPHeaderField:"DeviceId") let bodyStr = "string or data to add to body of request" let bodyData = bodyStr.data(using: String.Encoding.utf8, allowLossyConversion: true) request.httpBody = bodyData let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) -> Void in if let httpResponse = response as? HTTPURLResponse { print("responseCode \(httpResponse.statusCode)") } if error != nil { // You can handle error response here print("\(error)") } else { //Converting response to collection formate (array or dictionary) do { let jsonResult = (try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers)) //success code } catch { //failure code } } } task.resume()