【问题标题】:POST works with JQuery but does not work with XMLHttpRequestPOST 适用于 JQuery,但不适用于 XMLHttpRequest
【发布时间】:2021-06-22 14:38:58
【问题描述】:

所以我正在尝试从 Javascript 发布到我的服务器 (php),并且尝试不使用 JQuery。

此代码工作并将必要的数据发布到数据库

var msg = {};
msg['name'] = 'joe';
msg['message'] = 'why no work';

$.post(phpURL, msg, function(data) {});

但是这个没有

var xhr = new XMLHttpRequest();
xhr.open("POST", phpURL, true);
xhr.send(msg);

我什至查看了我的 php 日志,查看了标头,我能看到的 JQuery 与 XHR 的唯一区别是内容类型标头 "application/x-www-form-urlencoded; charset=UTF-8" 和此标头 "x-requested-with" "XMLHttpRequest"

所以我尝试了以下标题的所有组合。

var xhr = new XMLHttpRequest();
xhr.open("POST", phpURL, true);
//xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
//xhr.setRequestHeader('x-requested-with', 'XMLHttpRequest');
xhr.send(msg);

没有效果。

值得一提的是,如果我尝试在任何地方添加JSON.stringify(msg),它不起作用,无论是在 JQuery 还是在 XHR 中。但我想先让这个工作,并解释这个奇怪的差异。

我倾向于认为这是一个 Javascript 问题,因为 JQuery 帖子有效,此外,服务器的 GET 请求和我尝试发布到的同一个表也有效。

【问题讨论】:

  • 在发送原生 XHR 时,您已将要发送的数据格式化为 application/x-www-form-urlencoded 格式,jQuery 会自动为您完成。
  • 上面那个线程讨论了数据格式
  • 是的,谢谢你们,你们是对的。如果我将味精更改为 'name=bla&message=ble' 它确实有效。我想以 JSON 格式发送,因为我需要发送 utf8,但我想这将是另一个问题。
  • JSON 不是编码类型。如果要发送 JSON,则需要设置 Content-Type', 'text/plain; charset=UTF-8' 标头。在这种情况下,服务器上的数据读取与传统处理不同。
  • 如前所述,“服务器上的数据读取不同于传统的”。使用file_get_contents('php://input'); 读取值。它会将 JSON 作为字符串返回给您(前提是您发送了一个字符串化对象)。

标签: javascript jquery post xmlhttprequest


【解决方案1】:

Do not confuse JavaScript objects with JSON.

如果你将一个对象传递给 jQuery 的 data 参数,那么它会将其编码为 application/x-www-form-urlencoded 数据(不是 JSON!)。

如果您将 application/x-www-form-urlencoded 数据发布到 PHP,那么它将解析它并用它填充 $_POST 超全局。

如果您将对象传递给XMLHttpRequest 对象的send() 方法,那么它将不会为您编码。它会隐式调用 .toString() 并发送任何有用的信息。

要达到与 jQuery 相同的效果,您需要 encode the data yourself。别忘了还要设置Content-Type 标头!

const encoded = new URLSearchParams(Object.entries(msg)).toString();
const xhr = new XMLHttpRequest();
xhr.open("POST", phpURL, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(encoded);

如果您想发送 JSON,那么您还必须对其进行编码,但这只需使用 JSON.stringify() 即可完成,尽管您还需要设置 Content-Type 标头(这次设置为 application/json)。

const encoded = JSON.stringify(msg);
const xhr = new XMLHttpRequest();
xhr.open("POST", phpURL, true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(encoded);

但是,PHP 不会自动解析 JSON,所以 $_POST 将保持为空,所以你 need to parse it manually

<?php 
    $json = file_get_contents('php://input');
    $msg = json_decode($json);

【讨论】:

    【解决方案2】:

    jQuery 在发送 AJAX 请求时做了很多工作。它以 application/x-www-form-urlencoded 格式转换活动对象并修复标题,并根据参数执行其他任务。

    当您发送原生 XMLHttpRequest 时,您必须自己处理所有这些。在您所说的 cmets 中,您实际上想要发送 JSON。 JSON 不是 PHP 可以识别的标准表单内容类型,因此您必须以 application/json 格式发送它。像这样:

    var msg = {
        name: 'joe',
        message: 'why no work'
      },
      xhr = new XMLHttpRequest();
    
    xhr.open('POST', phpURL, true);
    xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
    // Add response handling here, if needed
    xhr.send(JSON.stringify(msg));
    

    但是,application/json 的内容类型在 PHP 中不被视为表单数据,$_POST 将为空。您可以从接收到的原始数据中读取数据,原始数据保存在特定文件中。像这样:

    $data = file_get_contents('php://input');
    // Results a string: '{"name":"joe","message":"why no work"}'
    

    现在您可以使用 json_decode($data) 将 JSON 转换为关联数组。

    【讨论】:

    • JSON 不是纯文本。 JSON 的内容类型是 application/json
    • @昆汀???从技术上讲,JSON 是纯文本,我会检查 application/json,等一下。
    • JSON 是文本,但它是格式化文本,而不是纯文本。
    • 如果您不编写代码来关注您发送的内容类型,那么这几乎是无关紧要的......但是一个可能会在未来绊倒您的不良做法(例如,如果您稍后切换您的后端并使用库来解析传入的数据(注意内容类型),而不是仅仅假设您将收到 JSON。
    • @Quentin 你说得对。看起来我周末有一些工作要做,我必须解决在我的网站上发送 JSON 数据的大量请求。
    猜你喜欢
    • 2020-10-08
    • 1970-01-01
    • 2011-05-24
    • 1970-01-01
    • 1970-01-01
    • 2015-09-19
    • 1970-01-01
    • 2021-09-08
    • 2017-01-25
    相关资源
    最近更新 更多