使用POST方法在Swift中进行HTTP请求

ang*_*ant 174 parameters post http-post httprequest swift

我正在尝试在Swift中运行HTTP请求,将POST 2参数发送到URL.

例:

链接: www.thisismylink.com/postName.php

PARAMS:

id = 13
name = Jack
Run Code Online (Sandbox Code Playgroud)

最简单的方法是什么?

我甚至不想阅读回复.我只是想发送它来通过PHP文件对我的数据库进行更改.

Rob*_*Rob 374

在Swift 3及更高版本中,您可以:

let url = URL(string: "http://www.thisismylink.com/postName.php")!
var request = URLRequest(url: url)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
let parameters: [String: Any] = [
    "id": 13,
    "name": "Jack & Jill"
]
request.httpBody = parameters.percentEscaped().data(using: .utf8)

let task = URLSession.shared.dataTask(with: request) { data, response, error in
    guard let data = data, 
        let response = response as? HTTPURLResponse, 
        error == nil else {                                              // check for fundamental networking error
        print("error", error ?? "Unknown error")
        return
    }

    guard (200 ... 299) ~= response.statusCode else {                    // check for http errors
        print("statusCode should be 2xx, but is \(response.statusCode)")
        print("response = \(response)")
        return
    }

    let responseString = String(data: data, encoding: .utf8)
    print("responseString = \(responseString)")
}

task.resume()
Run Code Online (Sandbox Code Playgroud)

哪里:

extension Dictionary {
    func percentEscaped() -> String {
        return map { (key, value) in
            let escapedKey = "\(key)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
            let escapedValue = "\(value)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
            return escapedKey + "=" + escapedValue
        }
        .joined(separator: "&")
    }
}

extension CharacterSet { 
    static let urlQueryValueAllowed: CharacterSet = {
        let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
        let subDelimitersToEncode = "!$&'()*+,;="

        var allowed = CharacterSet.urlQueryAllowed
        allowed.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
        return allowed
    }()
}
Run Code Online (Sandbox Code Playgroud)

这将检查基本网络错误以及高级HTTP错误.这也正确地百分比转义查询的参数.

注意,我使用的nameJack & Jill,以示出正确x-www-form-urlencoded的结果name=Jack%20%26%20Jill,这是"百分比编码"(即空间被替换%20并且&在值被替换为%26).


请参阅Swift 2演绎的此答案的上一版本.

  • 仅供参考,如果你想做真正的请求(包括转义百分比,创建复杂的请求,简化响应的解析),请考虑使用AFNetworking的作者[AlamoFire](https://github.com/Alamofire/Alamofire) .但是如果你只是想做一个简单的`POST`请求​​,你可以使用上面的. (7认同)
  • 谢谢罗布,这正是我要找的!只不过是一个简单的POST。很好的答案! (3认同)
  • @complexi - 我不会在 `$_POST` 和文件名之间建立连接,而是将其简化为更简单的东西:如果您没有获得正确的 URL,PHP 脚本将根本不会运行。但并非总是必须包含文件名(例如,服务器可能正在执行 URL 路由或具有默认文件名)。在本例中,OP 给了我们一个包含文件名的 URL,因此我只需使用与他相同的 URL。 (2认同)
  • 在这方面,Alamofire 并不比 URLSession 更好也不差。所有网络 API 本质上都是异步的,它们也应该如此。现在,如果您正在寻找处理异步请求的其他优雅方式,您可以考虑将它们(`URLSession` 请求或 Alamofire 请求)包装在异步的、自定义的 `Operation` 子类中。或者你可以使用一些承诺库,比如 PromiseKit。 (2认同)
  • @DeepBlue - 我明白你在说什么,但我不同意。如果出现问题,默默地失败是一个_非常_坏主意。也许你可以做`guard let url = ... else {fatalError("Invalid URL") }`,但这是语法上的噪音,没有什么好处。您正在为一些不是最终用户运行时问题而是编程问题错误编写大量错误处理代码的道路走下去。类比是隐式解包的`@IBOutlet` 引用。您是否为所有网点编写了大量的“guard let label = ...”代码?不,那太傻了。同样在这里。 (2认同)
  • 不要误会我的意思。如果有些事情不是很明显,或者可能由于程序员无法控制的原因而失败(例如解析 JSON 响应和/或处理网络错误),那么使用强制解包运算符是一个巨大的错误。绝对安全地打开那些。但是对于诸如`@IBOutlet` 或这个 URL 示例之类的东西,添加语法噪音会适得其反,恕我直言。并且用一个只执行“return”的“else”子句做一个“guard”,隐藏任何潜在的问题,是一个非常糟糕的主意。 (2认同)

Suh*_*til 55

Swift 3和swift 4

@IBAction func submitAction(sender: UIButton) {

    //declare parameter as a dictionary which contains string as key and value combination. considering inputs are valid

    let parameters = ["id": 13, "name": "jack"]

    //create the url with URL
    let url = URL(string: "www.thisismylink.com/postName.php")! //change the url

    //create the session object
    let session = URLSession.shared

    //now create the URLRequest object using the url object
    var request = URLRequest(url: url)
    request.httpMethod = "POST" //set http method as POST

    do {
        request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted) // pass dictionary to nsdata object and set it as request body
    } catch let error {
        print(error.localizedDescription)
    }

    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.addValue("application/json", forHTTPHeaderField: "Accept")

    //create dataTask using the session object to send data to the server
    let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in

        guard error == nil else {
            return
        }

        guard let data = data else {
            return
        }

        do {
            //create json object from data
            if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
                print(json)
                // handle json...
            }
        } catch let error {
            print(error.localizedDescription)
        }
    })
    task.resume()
}
Run Code Online (Sandbox Code Playgroud)

  • 我的代码出现以下错误"无法读取数据,因为格式不正确." (6认同)
  • 这应该是正确的答案,因为谁想要像检查的答案建议的那样将数据形成字符串......#oldSkool (2认同)

poi*_*tum 35

对于任何正在寻找一种干净的方式在 Swift 5 中对 POST 请求进行编码的人。

您不需要手动添加百分比编码。使用URLComponents创建一个GET请求URL。然后使用query该 URL 的属性来正确获取转义查询字符串的百分比。

let url = URL(string: "https://example.com")!
var components = URLComponents(url: url, resolvingAgainstBaseURL: false)!

components.queryItems = [
    URLQueryItem(name: "key1", value: "NeedToEscape=And&"),
    URLQueryItem(name: "key2", value: "vålüé")
]

let query = components.url!.query
Run Code Online (Sandbox Code Playgroud)

query会是一个正确转义字符串:

key1=NeedToEscape%3DAnd%26&key2=v%C3%A5l%C3%BC%C3%A9

现在您可以创建一个请求并将查询用作 HTTPBody:

var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = Data(query.utf8)
Run Code Online (Sandbox Code Playgroud)

现在您可以发送请求了。

  • 顺便说一句,如果您使用此技术,请注意它不会正确地对“+”字符进行百分比转义。请参阅 /sf/answers/1940723921/。 (3认同)
  • 经过各种示例后,只有这适用于 Swift 5。 (2认同)

Esq*_*uth 12

下面是我在日志库中使用的方法:https://github.com/goktugyil/QorumLogs

此方法填写Google表单中的html表单.

    var url = NSURL(string: urlstring)

    var request = NSMutableURLRequest(URL: url!)
    request.HTTPMethod = "POST"
    request.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
    request.HTTPBody = postData.dataUsingEncoding(NSUTF8StringEncoding)
    var connection = NSURLConnection(request: request, delegate: nil, startImmediately: true)
Run Code Online (Sandbox Code Playgroud)


Osm*_*man 8

let session = URLSession.shared
        let url = "http://...."
        let request = NSMutableURLRequest(url: NSURL(string: url)! as URL)
        request.httpMethod = "POST"
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        var params :[String: Any]?
        params = ["Some_ID" : "111", "REQUEST" : "SOME_API_NAME"]
        do{
            request.httpBody = try JSONSerialization.data(withJSONObject: params, options: JSONSerialization.WritingOptions())
            let task = session.dataTask(with: request as URLRequest as URLRequest, completionHandler: {(data, response, error) in
                if let response = response {
                    let nsHTTPResponse = response as! HTTPURLResponse
                    let statusCode = nsHTTPResponse.statusCode
                    print ("status code = \(statusCode)")
                }
                if let error = error {
                    print ("\(error)")
                }
                if let data = data {
                    do{
                        let jsonResponse = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions())
                        print ("data = \(jsonResponse)")
                    }catch _ {
                        print ("OOps not good JSON formatted response")
                    }
                }
            })
            task.resume()
        }catch _ {
            print ("Oops something happened buddy")
        }
Run Code Online (Sandbox Code Playgroud)


Can*_*ear 7

这里的所有答案都使用 JSON 对象。这给 $this->input->post() 我们的 Codeigniter 控制器的方法带来了问题。无法CI_Controller直接读取 JSON。我们使用这个方法来做到这一点,而不需要 JSON

func postRequest() {
    // Create url object
    guard let url = URL(string: yourURL) else {return}

    // Create the session object
    let session = URLSession.shared

    // Create the URLRequest object using the url object
    var request = URLRequest(url: url)

    // Set the request method. Important Do not set any other headers, like Content-Type
    request.httpMethod = "POST" //set http method as POST

    // Set parameters here. Replace with your own.
    let postData = "param1_id=param1_value&param2_id=param2_value".data(using: .utf8)
    request.httpBody = postData

    // Create a task using the session object, to run and return completion handler
    let webTask = session.dataTask(with: request, completionHandler: {data, response, error in
    guard error == nil else {
        print(error?.localizedDescription ?? "Response Error")
        return
    }
    guard let serverData = data else {
        print("server data error")
        return
    }
    do {
        if let requestJson = try JSONSerialization.jsonObject(with: serverData, options: .mutableContainers) as? [String: Any]{
            print("Response: \(requestJson)")
        }
    } catch let responseError {
        print("Serialisation in error in creating response body: \(responseError.localizedDescription)")
        let message = String(bytes: serverData, encoding: .ascii)
        print(message as Any)
    }

    // Run the task
    webTask.resume()
}
Run Code Online (Sandbox Code Playgroud)

现在您的CI_Controller 将能够获取param1param2使用$this->input->post('param1')$this->input->post('param2')