POST 适用于 JQuery 但不适用于 XMLHttpRequest

POST works with JQuery but does not work with XMLHttpRequest

所以我正在尝试从 Javascript POST 到我的服务器 (php) 并且我试图不使用 JQuery.

此代码有效并且post将必要的数据发送到数据库

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 日志,查看了 headers,我能看到的 JQuery 与 XHR 的唯一区别是 content-type header "application/x-www-form-urlencoded; charset=UTF-8" 和这个 header "x-requested-with" "XMLHttpRequest".

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

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 post 有效,此外,服务器的 GET 请求和相同的 table我正在尝试 post 工作。

jQuery 在发送 AJAX 请求时在幕后做了很多工作。它将实时 object 转换为 application/x-www-form-urlencoded 格式并修复 headers,并根据参数执行其他任务。

当您发送本机 XMLHttpRequest 时,您必须自己处理所有这些。在你说的评论里,你其实是想发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 转换为具有 json_decode($data) 的关联数组。

Do not confuse JavaScript objects with JSON.

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

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

如果您将 object 传递给 XMLHttpRequest object 的 send() 方法,那么它将 对其进行编码为你。它将隐式调用 .toString() 并且不会发送任何有用的东西。

要达到与 jQuery 相同的效果,您需要 encode the data yourself。不要忘记也设置 Content-Type header!

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 header(这次到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);