ios 使用 application/x-www-form-urlencoded 的 POST 请求
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22063959/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
POST request using application/x-www-form-urlencoded
提问by jmac
The back end developer had given these instructions in POST requests:
后端开发人员在 POST 请求中给出了以下说明:
- Route: {url}/{app_name/{controller}/{action}
- The controller and action should be on small caps.
- API test link: http:****************
- Request should be use POST Method.
- Parameters should be pass via request content body (FormUrlEncodedContent).
- Parameters should be on json format.
- Parameters are key sensitive.
- 路线:{url}/{app_name/{controller}/{action}
- 控制器和动作应该是小型股。
- API 测试链接:http: *** *** *** *** ****
- 请求应该使用 POST 方法。
- 参数应通过请求内容主体 (FormUrlEncodedContent) 传递。
- 参数应为 json 格式。
- 参数是键敏感的。
Having no experience with number 5 in the protocol, I searched and ended with my code.
由于对协议中的数字 5 没有经验,我搜索并以我的代码结束。
-(id)initWithURLString:(NSString *)URLString withHTTPMEthod:(NSString *)method withHTTPBody:(NSDictionary *)body {
_URLString = URLString;
HTTPMethod = method;
HTTPBody = body;
//set error message
errorMessage = @"Can't connect to server at this moment. Try again later";
errorTitle = @"Connection Error";
return self;
}
-(void)fireConnectionRequest {
NSOperationQueue *mainQueue = [[NSOperationQueue alloc] init];
[mainQueue setMaxConcurrentOperationCount:5];
NSError *error = Nil;
NSURL *url = [NSURL URLWithString:_URLString];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
NSData *sendData = [NSJSONSerialization dataWithJSONObject:HTTPBody options:NSJSONWritingPrettyPrinted error:&error];
[request setHTTPMethod:@"POST"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[request setHTTPBody: sendData];
[NSURLConnection connectionWithRequest:request delegate:self];
NSString *jsonString = [[NSString alloc]initWithData:sendData encoding:NSUTF8StringEncoding];
//fire URL connectiion request
[NSURLConnection sendAsynchronousRequest:request queue:mainQueue completionHandler:^(NSURLResponse *response, NSData *responseData, NSError *error) {
//get the return message and transform to dictionary
NSString *data = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
returnMessage = [NSJSONSerialization JSONObjectWithData: [data dataUsingEncoding:NSUTF8StringEncoding]
options: NSJSONReadingMutableContainers
error:&error];
//check return message
if (!error) {
[delegate returnMessageForTag:self.tag];
}
else {
[delegate returnErrorMessageForTag:self.tag];
}
}];
}
I pass a dictionary formatted to JSON. he agrees that I was able to pass the right data. And I was able to connect to the API, but it is always returning "FAILED" when I try send data for registration. There are no problems in connection, but I failed to transfer the data.
我传递了一个格式化为 JSON 的字典。他同意我能够传递正确的数据。我能够连接到 API,但是当我尝试发送数据进行注册时,它总是返回“失败”。连接没有问题,但我无法传输数据。
The android developer here using the same API has no problem with it, but wasn't able to help me out since he's not familiar with iOS.
这里使用相同 API 的 android 开发人员对此没有任何问题,但由于他不熟悉 iOS,因此无法帮助我。
What am I missing?
我错过了什么?
回答by Darshan Kunjadiya
Try like this code
试试这个代码
Objective C
目标 C
NSString *post =[NSString stringWithFormat:@"AgencyId=1&UserId=1&Type=1&Date=%@&Time=%@&Coords=%@&Image=h32979`7~U@)01123737373773&SeverityLevel=2",strDateLocal,strDateTime,dict];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:@"%d",[postData length]];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://google/places"]]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:postData];
NSError *error;
NSURLResponse *response;
NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *str=[[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
Swift 2.2
斯威夫特 2.2
var post = "AgencyId=1&UserId=1&Type=1&Date=\(strDateLocal)&Time=\(strDateTime)&Coords=\(dict)&Image=h32979`7~U@)01123737373773&SeverityLevel=2"
var postData = post.dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion: true)!
var postLength = "\(postData.length)"
var request = NSMutableURLRequest()
request.URL = NSURL(string: "http://google/places")!
request.HTTPMethod = "POST"
request.setValue(postLength, forHTTPHeaderField: "Content-Length")
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.HTTPBody = postData
NSError * error
NSURLResponse * response
var urlData = try! NSURLConnection.sendSynchronousRequest(request, returningResponse: response)!
var str = String(data: urlData, encoding: NSUTF8StringEncoding)
Swift 3.0
斯威夫特 3.0
let jsonData = try? JSONSerialization.data(withJSONObject: kParameters)
let url: URL = URL(string: "Add Your API URL HERE")!
print(url)
var request: URLRequest = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = jsonData
request.setValue(Constant.UserDefaults.object(forKey: "Authorization") as! String?, forHTTPHeaderField: "Authorization")
request.setValue(Constant.kAppContentType, forHTTPHeaderField: "Content-Type")
request.setValue(Constant.UserAgentFormat(), forHTTPHeaderField: "User-Agent")
let task = URLSession.shared.dataTask(with: request, completionHandler: { data, response, error in
if data != nil {
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! NSDictionary
print(json)
} catch let error as NSError {
print(error)
}
} else {
let emptyDict = NSDictionary()
}
})
task.resume()
Swift 4
斯威夫特 4
let headers = [
"Content-Type": "application/x-www-form-urlencoded"
]
let postData = NSMutableData(data: "UserID=351".data(using: String.Encoding.utf8)!)
let request = NSMutableURLRequest(url: NSURL(string: "Add Your URL Here")! as URL,
cachePolicy: .useProtocolCachePolicy,
timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
if (error != nil) {
print(error!)
} else {
let httpResponse = response as? HTTPURLResponse
print(httpResponse!)
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments)
print(json)
} catch {
print(error)
}
}
})
dataTask.resume()
Alamofire
阿拉莫菲尔
Alamofire.request("Add Your URL Here",method: .post, parameters: ["CategoryId": "15"])
.validate(contentType: ["application/x-www-form-urlencoded"])
.responseJSON { (response) in
print(response.result.value)
}
I hope this code useful for you.
我希望这段代码对你有用。
回答by Muarl
@fatihyildizhan
@fatihyildizhan
not enough reputation to directly comment your answer therefore this answer.
没有足够的声誉来直接评论你的答案,因此这个答案。
Swift 1.2
斯威夫特 1.2
let myParams = "username=user1&password=12345"
let postData = myParams.dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion: true)
let postLength = String(format: "%d", postData!.length)
var myRequest = NSMutableURLRequest(URL: self.url)
myRequest.HTTPMethod = "POST"
myRequest.setValue(postLength, forHTTPHeaderField: "Content-Length")
myRequest.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
myRequest.HTTPBody = postData
var response: AutoreleasingUnsafeMutablePointer<NSURLResponse?> = nil
This code above just works fine in my case.
上面的代码在我的情况下工作正常。
回答by Manikandan
Swift 4
斯威夫特 4
let params = ["password":873311,"username":"jadon","client_id":"a793fb82-c978-11e9-a32f-2a2ae2dbcce4"]
let jsonString = params.reduce("") { "\(let body2 = ["username": "[email protected]",
"password": "111",
"client_secret":"7E",
"grant_type":"password"]
let data : Data = query(body2).data(using: .utf8, allowLossyConversion: false)!
var request : URLRequest = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField:"Content-Type");
request.setValue(NSLocalizedString("lang", comment: ""), forHTTPHeaderField:"Accept-Language");
request.httpBody = data
do {...}
}
public func queryComponents(fromKey key: String, value: Any) -> [(String, String)] {
var components: [(String, String)] = []
if let dictionary = value as? [String: Any] {
for (nestedKey, value) in dictionary {
components += queryComponents(fromKey: "\(key)[\(nestedKey)]", value: value)
}
} else if let array = value as? [Any] {
for value in array {
components += queryComponents(fromKey: "\(key)[]", value: value)
}
} else if let value = value as? NSNumber {
if value.isBool {
components.append((escape(key), escape((value.boolValue ? "1" : "0"))))
} else {
components.append((escape(key), escape("\(value)")))
}
} else if let bool = value as? Bool {
components.append((escape(key), escape((bool ? "1" : "0"))))
} else {
components.append((escape(key), escape("\(value)")))
}
return components
}
public func escape(_ string: String) -> String {
let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
let subDelimitersToEncode = "!$&'()*+,;="
var allowedCharacterSet = CharacterSet.urlQueryAllowed
allowedCharacterSet.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
var escaped = ""
if #available(iOS 8.3, *) {
escaped = string.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? string
} else {
let batchSize = 50
var index = string.startIndex
while index != string.endIndex {
let startIndex = index
let endIndex = string.index(index, offsetBy: batchSize, limitedBy: string.endIndex) ?? string.endIndex
let range = startIndex..<endIndex
let substring = string.substring(with: range)
escaped += substring.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? substring
index = endIndex
}
}
return escaped
}
)\(.0)=\(.1)&" }
let jsonData = jsonString.data(using: .utf8, allowLossyConversion: false)!
urlRequest.addValue("application/x-www-form-urlencoded", forHTTPHeaderField:"Content-Type")
urlRequest.httpBody = jsonData
回答by Diego Renau
With Swift 3, let jsonData = try? JSONSerialization.data(withJSONObject: kParameters)didn't work fine for me, so i had to copy the AlamoFire solution...
使用 Swift 3,让 jsonData = 试试?JSONSerialization.data(withJSONObject: kParameters)对我不起作用,所以我不得不复制 AlamoFire 解决方案......
extension NSNumber {
fileprivate var isBool: Bool { return CFBooleanGetTypeID() == CFGetTypeID(self) }}
And one extension:
还有一个扩展:
func percentEscapeString(_ string: String) -> String {
var characterSet = CharacterSet.alphanumerics
characterSet.insert(charactersIn: "-._* ")
return string
.addingPercentEncoding(withAllowedCharacters: characterSet)!
.replacingOccurrences(of: " ", with: " ")
.replacingOccurrences(of: " ", with: " ", options: [], range: nil)
.replacingOccurrences(of: "\"", with: "", options: NSString.CompareOptions.literal, range:nil)
}
// Set encoded values to Dict values you can decode keys if required
dictData.forEach { (key, value) in
if let val = value as? String {
dictData[key] = self.percentEscapeString(val)
} else {
dictData[key] = value
}
}
This is temporary, It has to be a better solution...
这是暂时的,它必须是一个更好的解决方案......
Hope it help...
希望它有帮助...
回答by Gurjinder Singh
Swift 4.2
斯威夫特 4.2
var urlParser = URLComponents()
urlParser.queryItems = [
URLQueryItem(name: "name", value: "Tim Tebow"),
URLQueryItem(name: "desc", value: "Gators' QB")
]
let httpBodyString = urlParser.percentEncodedQuery
This worked for me and here is link of source https://gist.github.com/HomerJSimpson/80c95f0424b8e9718a40
这对我有用,这里是源链接https://gist.github.com/HomerJSimpson/80c95f0424b8e9718a40
回答by Jeff Collier
Swift does offer a function for URL-%-encoding, but it is not an exact match as noted by @nolanw in the 1st comment. For Step 5 in the original question, once you have the key-value pairs in some structure, here is a short and simple alternative for encoding (Swift 4.2):
Swift 确实提供了一个用于 URL-%-encoding 的函数,但它不是@nolanw 在第一条评论中指出的完全匹配。对于原始问题中的第 5 步,一旦您拥有某种结构中的键值对,这里有一个简短而简单的编码替代方案(Swift 4.2):
name=Tim%20Tebow&desc=Gators'%20QB
Paste that into an Xcode playground, and add print(httpBodyString!)
. In the output, you will see:
将其粘贴到 Xcode playground,然后添加print(httpBodyString!)
. 在输出中,您将看到:
extension String {
static let formUrlencodedAllowedCharacters =
CharacterSet(charactersIn: "0123456789" +
"abcdefghijklmnopqrstuvwxyz" +
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
"-._* ")
public func formUrlencoded() -> String {
let encoded = addingPercentEncoding(withAllowedCharacters: String.formUrlencodedAllowedCharacters)
return encoded?.replacingOccurrences(of: " ", with: "+") ?? ""
}
}
class HTTPUtils {
public class func formUrlencode(_ values: [String: String]) -> String {
return values.map { key, value in
return "\(key.formUrlencoded())=\(value.formUrlencoded())"
}.joined(separator: "&")
}
}
let headers = [
"content-type": "application/x-www-form-urlencoded; charset=utf-8"
]
let body = HTTPUtils.formUrlencode([
"field": "value"
])
var request = try URLRequest(url: url, method: .post, headers: headers)
request.httpBody = body.data(using: .utf8)
URLSession.shared.dataTask(with: request, completionHandler: { ... }).resume()
Note: This is for percent-encoding set of basic form values (i.e. not binary data and not multi-part)
注意:这是用于基本形式值的百分比编码集(即不是二进制数据也不是多部分)
回答by Zmey
This version handles encoding of parameters and replacing spaces with '+'.
此版本处理参数编码并用“+”替换空格。
-(NSData *)encodeParameters:(NSDictionary *)parameters {
NSMutableArray *list = [NSMutableArray new];
for (NSString *key in [parameters allKeys]) {
id obj = [parameters objectForKey:key];
NSString *path = [NSString stringWithFormat:@"%@=%@", key, obj];
[list addObject:path];
}
return [[list componentsJoinedByString:@"&"] dataUsingEncoding:NSUTF8StringEncoding];
回答by Mantas Laurinavi?ius
Parse dictionary params to string:
将字典参数解析为字符串:
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:[self encodeParameters:parameters]];
}
}
And use it:
并使用它:
let myParams:NSString = "username=user1&password=12345"
let myParamsNSData:NSData = NSData(base64EncodedString: myParams, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)!
let myParamsLength:NSString = NSString(UTF8String: myParamsNSData.length)
let myRequest: NSMutableURLRequest = NSURL(fileURLWithPath: self.url)
myRequest.HTTPMethod = "POST"
myRequest.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
myRequest.HTTPBody = myParamsNSData
var data2: NSData!
var error2: NSError!
回答by fatihyildizhan
Is it possible to convert this code to swift ? I already tried but could not handle it. Maybe this code block may help you. Thanks.
是否可以将此代码转换为 swift ?我已经尝试过但无法处理。也许这个代码块可以帮助你。谢谢。
let params:[String: Any]
if "application/x-www-form-urlencoded" {
let bodyData = params.stringFromHttpParameters()
self.request.httpBody = bodyData.data(using: String.Encoding.utf8)}
if "application/json"{
do {
self.request.httpBody = try JSONSerialization.data(withJSONObject: params, options: JSONSerialization.WritingOptions())
} catch {
print("bad things happened")
}
}
回答by Arturo Silva
func stringFromHttpParameters() -> String {
let parameterArray = self.map { (key, value) -> String in let percentEscapedKey = (key as!String).stringByAddingPercentEncodingForURLQueryValue()!
let percentEscapedValue = (value as! String).stringByAddingPercentEncodingForURLQueryValue()!}
return "\(percentEscapedKey)=\(percentEscapedValue)"}
return parameterArray.joined(separator: "&")}
extension Dictionary
扩展词典
##代码##