我应该对 POST 数据进行 URL 编码吗?

Posted

技术标签:

【中文标题】我应该对 POST 数据进行 URL 编码吗?【英文标题】:Should I URL-encode POST data? 【发布时间】:2011-09-30 01:00:41 【问题描述】:

我正在将数据发布到外部 API(如果相关,则使用 php)。

我应该对我传递的 POST 变量进行 URL 编码吗?

还是我只需要对 GET 数据进行 URL 编码?


更新:这是我的 PHP,以防相关:

$fields = array(
    'mediaupload'=>$file_field,
    'username'=>urlencode($_POST["username"]),
    'password'=>urlencode($_POST["password"]),
    'latitude'=>urlencode($_POST["latitude"]),
    'longitude'=>urlencode($_POST["longitude"]),
    'datetime'=>urlencode($_POST["datetime"]),
    'category'=>urlencode($_POST["category"]),
    'metacategory'=>urlencode($_POST["metacategory"]),
    'caption'=>($_POST["description"])
);
$fields_string = http_build_query($fields);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST,count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS,$fields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);

【问题讨论】:

这是 API,供参考:cyclestreets.net/api - 它似乎没有指定它所期望的。 【参考方案1】:

一般回答

您的问题的一般答案是视情况而定。您可以通过在 HTTP 标头中指定您的“Content-Type”来决定。

“application/x-www-form-urlencoded”值意味着您的 POST 正文需要像 GET 参数字符串一样进行 URL 编码。 “multipart/form-data”的值意味着您将使用内容分隔符而不是对内容进行 url 编码。

This answer has a much more thorough explanation如果您想了解更多信息。


具体答案

对于您正在使用的 PHP 库 (CURL) 的特定答案,您应该read the documentation here。

以下是相关信息:

CURLOPT_POST

TRUE 以执行常规 HTTP POST。 这个 POST 是普通的 application/x-www-form-urlencoded 类型,最常用于 html 表单。

CURLOPT_POSTFIELDS

要在 HTTP“POST”操作中发布的完整数据。要发布文件,请在文件名前加上 @ 并使用完整路径。可以通过使用格式为“;type=mimetype”的文件名来明确指定文件类型。此参数可以作为 urlencoded 字符串(如 'para1=val1&para2=val2&...')或作为字段名称作为键和字段数据作为值的数组传递。如果 value 是一个数组,则 Content-Type 标头将设置为 multipart/form-data。从 PHP 5.2.0 开始,如果文件以 @ 前缀传递给此选项,则 value 必须是数组。

【讨论】:

【参考方案2】:

@DougW 已经明确回答了这个问题,但我还是想在这里添加一些代码来解释 Doug 的观点。 (并更正上面代码中的错误)

解决方案 1:使用内容类型标头对 POST 数据进行 URL 编码 :application/x-www-form-urlencoded 。

注意:你不需要对$_POST[]字段一一进行urlencode,http_build_query()函数可以很好地完成urlencoding工作。

$fields = array(
    'mediaupload'=>$file_field,
    'username'=>$_POST["username"],
    'password'=>$_POST["password"],
    'latitude'=>$_POST["latitude"],
    'longitude'=>$_POST["longitude"],
    'datetime'=>$_POST["datetime"],
    'category'=>$_POST["category"],
    'metacategory'=>$_POST["metacategory"],
    'caption'=>$_POST["description"]
);

$fields_string = http_build_query($fields);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$fields_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);

解决方案2:直接将数组作为post数据传递,不进行URL编码,而Content-Type标头将设置为multipart/form-data。

$fields = array(
        'mediaupload'=>$file_field,
        'username'=>$_POST["username"],
        'password'=>$_POST["password"],
        'latitude'=>$_POST["latitude"],
        'longitude'=>$_POST["longitude"],
        'datetime'=>$_POST["datetime"],
        'category'=>$_POST["category"],
        'metacategory'=>$_POST["metacategory"],
        'caption'=>$_POST["description"]
    );

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL,$url);
    curl_setopt($ch, CURLOPT_POST,1);
    curl_setopt($ch, CURLOPT_POSTFIELDS,$fields);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $response = curl_exec($ch);

两种代码 sn-ps 都可以工作,但使用不同的 HTTP 标头和正文。

【讨论】:

http_build_query() function can do the urlencoding job nicely. 谢谢这是我几天来一直在寻找的。`【参考方案3】:

curl 将为您编码数据,只需将原始字段数据放入 fields 数组并告诉它“开始”。

【讨论】:

我花了几个小时来修复一个 php curl 脚本,其中目标 ASP 网页在发送 curl 发布数据后将我重定向到错误页面,但我无法弄清楚原因。然后在对帖子数据进行 url 编码后,它起作用了,我开始得到预期的结果。 看是不是数组,然后curl会自动进行urlencoded。如果是作为字符串传递的,我们需要先进行urlencode。【参考方案4】:

以上帖子回答了与 URL 编码及其工作原理相关的问题,但最初的问题是“我应该对 POST 数据进行 URL 编码吗?”没有回答。

根据我最近使用 URL 编码的经验,我想进一步扩展这个问题。 “我是否应该对 POST 数据进行 URL 编码,与 GET HTTP 方法相同。通常,浏览器上的 HTML 表单如果已填写、提交和/或获取一些信息,浏览器将执行 URL 编码,但如果应用程序公开 Web 服务并期望消费者对数据进行 URL 编码,使用 POST HTTP 方法进行 URL 编码在架构和技术上是否正确?”

【讨论】:

以上是关于我应该对 POST 数据进行 URL 编码吗?的主要内容,如果未能解决你的问题,请参考以下文章

POST请求 之 对数据进行编码处理

在 bash 脚本中对字符串进行 URL 编码

urllib 学习二

在 Objective-c 中使用 AFNetworking 对字典进行 URL 编码

URL中的空格、加号究竟应该使用何种方式编码

如何在 Flutter/Dart 中使用 url 编码的标头和正文发出 HTTP POST 请求