问题
I'm trying to remove jQuery from some code. I only use it for POST operations so I want to drop it and use fetch() instead. But I can't get fetch() to work using the same data. The php file is working OK, it is just not receiving the data
This sets up the test data for both test cases below:
var toPostObj = new(Object);
toPostObj.action = "update+file";
toPostObj.arrays = [["2020-12-28", "23:20:56", "Trying from ztest", "9.jpg"]];
This works using jQuery:
$.post('toMariaDB.php', { // url
data: toPostObj
}, function(data2, status, jqXHR) {
console.log ("data2",data2);
});
This does not work using 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)
})
For debugging purposes, toMariaDB.php writes out a log file of the data it receives and any other messages from toMariaDB.
Running the jQuery code writes this to the log file:
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
)
)
)
which is what toMariaDB.php expects.
But the fetch() version writes this:
toMariaDB: I've ARRIVED
in toMariaDB 1=>
The result for fetch() is the same whether I use
body: toPostObj,
or
body: JSON.stringify(toPostObj),
I've used
headers: { "Content-type": "application/text; charset=UTF-8" }
since toMariaDB.php returns text and, as I understand it, headers describes what is returned
but just in case I had misunderstood, I tried
headers: { "Content-type": "application/json; charset=UTF-8" }
as well, but that didn't work either.
How can I format the body so that it arrives at toMariaDB.php in the same form as with jQuery? I.e.
toPostObj.action = "update+file";
toPostObj.arrays = [["2020-12-28", "23:20:56", "Trying from ztest", "9.jpg"]];
Thanks for any help.
EDIT
As suggested by @T.J.Crowder, (thanks for pointing me at that) here's what the Network tab shows as the Request Payload when running with 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
I don't understand why these don't show as data[arrays][0][0], etc., but it works.
(It's a 2D array because toMariaDB.php has to be able to process multiple arrays.)
With fetch(), the Network tab Request Payload shows:
[object Object]
回答1:
From the documentation we can see that...
When data is an object, jQuery generates the data string from the object's key/value pairs unless the
processData
option is set to false. For example,{ a: "bc", d: "e,f" }
is converted to the string"a=bc&d=e%2Cf"
. If the value is an array, jQuery serializes multiple values with same key based on the value of the traditional setting (described below). For example,{ a: [1,2] }
becomes the string"a%5B%5D=1&a%5B%5D=2"
with the defaulttraditional: false
setting.
(It doesn't say so, but it does it recursively.)
Your code is sending an object with a single top-level property called data
whose value is your toPostObj
, which in turn has properties with string and array values. It ends up sending a POST body that looks like this:
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
...which is these parameters:
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
You can replicate that with a URLSearchParams object like this:
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
will handle the URI-escaping etc. for you.
回答2:
I think you'd have the best experience using this:
fetch("toMariaDB.php", {
method: "POST",
body: JSON.stringify(toPostObj),
headers: {
"Content-type": "application/json",
},
})
And doing json_decode
on the PHP side.
If you want to exactly replicate what jQuery does, you'll have to look into the network tab as it can differ... but most likely it's using application/x-www-form-urlencoded
as the content type. Best way to replicate that is to populate a FormData
object which is still quite a hassle when you have arrays, especially nested arrays.
来源:https://stackoverflow.com/questions/65481693/how-do-i-get-fetch-to-post-data-the-same-way-as-jquery-does