如何在Swift中传递HTTPPost请求中的参数



我正在开发一个简单的Swift测试应用程序,它只在我的服务器上调用Perl脚本。现在我只想发送一个用户名和id,并在JSON响应中返回它们。没什么,我还在学习阶段。

但无论我尝试哪种方式,我都无法成功发送URLRequest中的两个参数。

在下面的示例中,你会看到我试图在主url中发送它们,我试图将它们添加为HTTPHeaderFields,但我在URLSessionDataDelegate中得到的响应总是:

数据是{"用户ID":","用户名":"JSON可选({userid=";username=";

let file = File(link: "http://example.com/cgi-bin/swift.pl?username=John&userid=01", data: "hello")
uploadService.start(file: file)

在我的URLSession实例中,我尝试过:

// From one of my view controllers I create a File struct 
// from a YouTube lesson. Eventually I want to send a file. 
// So for now am using just *Hello*:
let uploadTask = UploadTask(file: file)
let url = URL(string: file.link)!
let uploadData = Data(file.data.utf8)

var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField:"Content-Type")

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

request.addValue("John", forHTTPHeaderField: "username")
request.addValue("01", forHTTPHeaderField: "userid")
uploadTask.task = uploadSession.uploadTask(with: request, from: uploadData)
uploadTask.task?.resume()

Swift测试的每一个其他部分都有效,我在URSessionDelegate中都会得到响应和数据,没有错误。显然,我只是不知道如何正确地发送这两个参数。备案:

  • 下面的Perl脚本可以在linux命令行中工作,或者在从web浏览器调用时工作。

  • 如果我在下面的perl脚本中硬编码返回repsonse,我会在URLSessionDelegate中收到它,这样我就知道我对它的解析是正确的

  • 此外,我的服务器的错误日志显示$header1和$header2从未初始化。

#!/usr/bin/perl -w
use strict;
use CGI;
use JSON;
my $q = new CGI;
my $header1 = $q->param("username");
my $header2 = $q->param("userid");
print $q->header('application/json');
my %out = (username=>"$header1", userid=>"$header2");
my $json = encode_json %out;
print $json;
exit(0);

您将参数username和userid作为http头值发送。您的perl-scrip期望它们是一个查询参数。因此,首先创建一个URLComponents对象,然后添加查询项,最后创建您的url。

试试这个:

let uploadTask = UploadTask(file: file)
var urlComponents = URLComponents(string: file.link)!
let queryItems = [URLQueryItem(name: "username", value: "John"),
URLQueryItem(name: "userid", value: "01")]
urlComponents.queryItems = queryItems
let url = urlComponents.url!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField:"Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
uploadTask.task = uploadSession.uploadTask(with: request, from: 
uploadData)
uploadTask.task?.resume()

看看这篇文章,它展示了如何使用URL 的扩展添加查询参数

在这两行中:

request.addValue("John", forHTTPHeaderField: "username")
request.addValue("01", forHTTPHeaderField: "userid")

您添加的是http头,而不是url查询参数。

要添加查询参数,需要先转换为URLComponents,然后再转换回:https://developer.apple.com/documentation/foundation/urlcomponents

var urlComponents = URLComponents(string: file.link)!
urlComponents.queryItems = [
URLQueryItem(name: "username", value: "name"),
URLQueryItem(name: "userid", value: "id")
]
let newURL = urlComponents.url!
//use the newURL

只需创建一个带有数据的字典

let parameterDictionary = ["username" : "John", "userid": "01"]

然后使用创建httpBody对象

guard let httpBody = try? JSONSerialization.data(withJSONObject: parameterDictionary, options: []) else { return }

然后简单地将该主体添加到您的请求参数中

request.httpBody = httpBody

我终于在StackOverflow上找到了答案。

由于没有http方法的经验,我的问题的简短答案是,如果我使用"http";GET";,我会使用urlComponents.queryItems,但如果我使用";POST";那么我的参数必须在http主体中。

但更重要的是,链接中的答案解释了你应该在何时以及为什么使用";获取";与";POST";,反之亦然。

因此,对于任何遇到这个问题的人,一定要阅读链接中提供的答案。

最新更新