【问题标题】:How do I get fetch() to POST data the same way as jQuery does?如何让 fetch() 以与 jQuery 相同的方式发布数据?
【发布时间】:2021-04-05 11:10:42
【问题描述】:

我正在尝试从一些代码中删除 jQuery。我只将它用于 POST 操作,所以我想删除它并使用 fetch() 代替。但我无法让 fetch() 使用相同的数据工作。 php文件工作正常,只是没有接收到数据

这将为以下两个测试用例设置测试数据:

var toPostObj = new(Object);
toPostObj.action = "update+file";
toPostObj.arrays = [["2020-12-28", "23:20:56", "Trying from ztest", "9.jpg"]];

这可以使用 jQuery:

$.post('toMariaDB.php', {  // url
    data: toPostObj 
}, function(data2, status, jqXHR) {
    console.log ("data2",data2);
});

这在使用 fetch() 时不起作用:

fetch("toMariaDB.php", { 
    method: "POST", 
    body: toPostObj,   // using JSON.stringify(toPostObj) also doesn't work 
    headers: { "Content-type": "application/text; charset=UTF-8" } 
}) 
.then(response => response.text()) 
.then(text => console.log(text))//; 
.catch(error => {
    console.error(error)
})

出于调试目的,toMariaDB.php 将其接收的数据和来自 toMariaDB 的任何其他消息写出一个日志文件。
运行 jQuery 代码会将其写入日志文件:

toMariaDB: I've ARRIVED
in toMariaDB 1=>Array
(
    [action] => update+file
    [arrays] => Array
        (
            [0] => Array
                (
                    [0] => 2020-12-28
                    [1] => 23:20:56
                    [2] => Trying from ztest
                    [3] => 9.jpg
                )

        )
)

这是 toMariaDB.php 所期望的。
但是 fetch() 版本是这样写的:

toMariaDB: I've ARRIVED
in toMariaDB 1=>

无论我使用 fetch() 的结果都是一样的

body: toPostObj,   

body: JSON.stringify(toPostObj),

我用过

headers: { "Content-type": "application/text; charset=UTF-8" } 

因为 toMariaDB.php 返回文本,据我了解,标题描述了返回的内容
但以防万一我误解了,我尝试了

headers: { "Content-type": "application/json; charset=UTF-8" } 

也一样,但这也没用。

如何格式化正文,使其以与 jQuery 相同的形式到达 toMariaDB.php?即

toPostObj.action = "update+file";
toPostObj.arrays = [["2020-12-28", "23:20:56", "Trying from ztest", "9.jpg"]];

感谢您的帮助。

编辑

正如@T.J.Crowder 所建议的,(感谢您指点我)这是使用 jQuery 运行时“网络”选项卡显示为“请求有效负载”的内容:

data[action]: update+file
data[arrays][0][]: 2020-12-28
data[arrays][0][]: 23:20:56
data[arrays][0][]: Trying from ztest
data[arrays][0][]: 9.jpg

我不明白为什么这些不显示为 data[arrays][0][0] 等,但它有效。
(这是一个二维数组,因为 toMariaDB.php 必须能够处理多个数组。)

使用 fetch(),Network 选项卡 Request Payload 显示:

[object Object]

【问题讨论】:

  • 请在浏览器中打开“网络”选项卡,运行 jQuery 代码,找到正在发送的 POST 正文,然后将其复制并粘贴到问题中。
  • 附注,FWIW:var toPostObj = new(Object); 是一种非常不寻常的写var toPostObj = new Object;的方式,这反过来又有点不寻常(但完全有效)写var toPostObj = new Object();的方式,通常最好写var toPostObj = {};
  • 谢谢,@T.J. Crowder,为 cmets 制作新物体。从 stackoverflow 或其他地方复制一些其他代码时,我选择了 new(Object) 样式。当我通过 var arr = []; 创建一个新数组时你的观察很有意义。我会记住的。

标签: javascript php jquery fetch-api


【解决方案1】:

the documentation我们可以看到...

当 data 是一个对象时,jQuery 从对象的键/值对生成数据字符串,除非 processData 选项设置为 false。例如,{ a: "bc", d: "e,f" } 转换为字符串 "a=bc&d=e%2Cf"。如果 value 是一个数组,jQuery 会根据传统设置的 value 序列化具有相同 key 的多个值(如下所述)。例如,{ a: [1,2] } 变为字符串 "a%5B%5D=1&a%5B%5D=2" 并具有默认的 traditional: false 设置。

(它没有这么说,但它递归地这样做。)

您的代码正在发送一个对象,该对象具有一个名为data 的顶级属性,其值为您的toPostObj,而该属性又具有字符串和数组值的属性。它最终会发送一个如下所示的 POST 正文:

data%5Baction%5D=update%2Bfile&data%5Barrays%5D%5B0%5D%5B%5D=2020-12-28&data%5Barrays%5D%5B0%5D%5B%5D=23%3A20%3A56&data%5Barrays%5D%5B0%5D%5B%5D=Trying+from+ztest&data%5Barrays%5D%5B0%5D%5B%5D=9.jpg

...就是这些参数:

data[action]: update+file
data[arrays][0][]: 2020-12-28
data[arrays][0][]: 23:20:56
data[arrays][0][]: Trying from ztest
data[arrays][0][]: 9.jpg

您可以像这样使用URLSearchParams object 复制它:

var toPostObj = new URLSearchParams();
toPostObj.append("data[action]", "update+file");
toPostObj.append("data[arrays][0][]", "2020-12-28");
toPostObj.append("data[arrays][0][]", "23:20:56");
toPostObj.append("data[arrays][0][]", "Trying from ztest");
toPostObj.append("data[arrays][0][]", "9.jpg");
fetch("foo", {
    method: "POST",
    body: toPostObj
})
// ...

URLSearchParams 将为您处理 URI 转义等。

【讨论】:

  • FormData 将生成多部分/表单数据数据,您希望 URLSearchParams 复制 jQuery 所做的。
  • @Quentin - 啊!你当然是对的。虽然我怀疑接收它的 PHP 代码是否会关心...
  • 没错,就开发人员而言,PHP 以透明且相同的方式处理多部分和 urlencoded 数据。 (但对于使用不同后端的人来说,值得记住)。
  • 我不知道评论是否适合这个,但这是一个教育和最好的stackoverflow示例。谢谢。
  • 谢谢,这让我了解了如何传输数据,现在它正在工作。显然我不能接受两个答案,但我愿意。
【解决方案2】:

我认为您将获得最好的使用体验:

fetch("toMariaDB.php", { 
    method: "POST", 
    body: JSON.stringify(toPostObj),
    headers: {
        "Content-type": "application/json",
    },
}) 

在 PHP 端做json_decode

如果您想完全复制 jQuery 的功能,您必须查看网络选项卡,因为它可能会有所不同……但很可能它使用 application/x-www-form-urlencoded 作为内容类型。最好的复制方法是填充 FormData 对象,当您有数组时,这仍然很麻烦,尤其是嵌套数组。

【讨论】:

  • 为了记录,我无法完成这项工作,但谢谢。
  • 本来我的印象是OP不能改变PHP端,但是从后来的cmet看来,好像可以。如果可以的话,这是一个不错的选择。
  • 我可以访问所有代码和服务器。我尝试了@Džuris 的建议,toMariaDB.php 报告说什么也没看到,或者无法解释它收到的内容。我更喜欢这种方法,因为它更简单,尤其是在处理嵌入式数组时。我无法让它工作,因为它显示“PHP Notice: Undefined index: data in /var/www/html/t3/toMariaDB.php on ...” 我现在使用 TJCrowder 方式,但我稍后我会回来解决这个问题,因为一旦我能找出哪里出错了,它就会变得更加简单。
  • @RoyGrubb 您是否尝试过 TJ 在其他评论线程中链接的方法?您应该能够通过file_get_contents('php://input') 而不是$_POST 找到发布的JSON。
  • 该链接由 T.J.为我解决了这个问题,感谢您的推动。
猜你喜欢
  • 1970-01-01
  • 2012-04-08
  • 1970-01-01
  • 2020-04-27
  • 1970-01-01
  • 1970-01-01
  • 2021-01-07
  • 1970-01-01
  • 2012-08-16
相关资源
最近更新 更多