我如何post表单数据与获取api?

我的代码:

fetch("api/xxx", {
body: new FormData(document.getElementById("form")),
headers: {
"Content-Type": "application/x-www-form-urlencoded",
// "Content-Type": "multipart/form-data",
},
method: "post",
}

我尝试使用fetch api发布我的表单,它发送的正文是这样的:

-----------------------------114782935826962
Content-Disposition: form-data; name="email"


test@example.com
-----------------------------114782935826962
Content-Disposition: form-data; name="password"


pw
-----------------------------114782935826962--

(我不知道为什么每次发送的时候boundary里的数字都会变…)

我想用“Content-Type”:“application/x-www-form-urlencoded”发送数据,我该怎么做?或者如果我必须处理它,我如何解码控制器中的数据?


请回答我的问题,我知道我能做到:

fetch("api/xxx", {
body: "email=test@example.com&password=pw",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
method: "post",
}

我想要的是像$(“#form”).serialize()在jQuery (w/o使用jQuery)或解码控制器中的多部分/表单数据的方法。谢谢你的回答。

397153 次浏览

可以将body设置为URLSearchParams的实例,并将查询字符串作为参数传递

fetch("/path/to/server", {
method:"POST"
, body:new URLSearchParams("email=test@example.com&password=pw")
})

document.forms[0].onsubmit = async(e) => {
e.preventDefault();
const params = new URLSearchParams([...new FormData(e.target).entries()]);
// fetch("/path/to/server", {method:"POST", body:params})
const response = await new Response(params).text();
console.log(response);
}
<form>
<input name="email" value="test@example.com">
<input name="password" value="pw">
<input type="submit">
</form>

客户端

不要设置内容类型标头。

// Build formData object.
let formData = new FormData();
formData.append('name', 'John');
formData.append('password', 'John123');


fetch("api/SampleData",
{
body: formData,
method: "post"
});

服务器

使用FromForm属性指定绑定源为表单数据。

[Route("api/[controller]")]
public class SampleDataController : Controller
{
[HttpPost]
public IActionResult Create([FromForm]UserDto dto)
{
return Ok();
}
}


public class UserDto
{
public string Name { get; set; }
public string Password { get; set; }
}

引用MDN在FormData(强调我的):

FormData接口提供了一种方法,可以轻松地构造一组表示表单字段及其值的键/值对,然后可以使用XMLHttpRequest.send()方法轻松地发送这些值。它使用与编码类型设置为"multipart/form-data"的表单相同的格式

因此,当使用FormData时,你将自己锁定在multipart/form-data中。没有办法将FormData对象作为对象体发送,而multipart/form-data格式发送数据。

如果你想要以application/x-www-form-urlencoded的形式发送数据,你必须将数据体指定为一个url编码的字符串,或者传递一个URLSearchParams对象。不幸的是,后者不能直接从form元素初始化。如果你不想自己遍历你的表单元素(你可以用可以来做),你也可以从FormData对象创建一个URLSearchParams对象:

const data = new URLSearchParams();
for (const pair of new FormData(formElement)) {
data.append(pair[0], pair[1]);
}


fetch(url, {
method: 'post',
body: data,
})
.then(…);

注意,你不需要自己指定Content-Type标头。


正如注释中的monk-time所指出的,你也可以创建URLSearchParams并直接传递FormData对象,而不是在循环中追加值:

const data = new URLSearchParams(new FormData(formElement));

不过,在浏览器中仍然有一些实验性的支持,所以在使用它之前一定要进行适当的测试。

使用FormDatafetch抓取和发送数据

fetch(form.action, {method:'post', body: new FormData(form)});

function send(e,form) {
fetch(form.action, {method:'post', body: new FormData(form)});


console.log('We send post asynchronously (AJAX)');
e.preventDefault();
}
<form method="POST" action="myapi/send" onsubmit="send(event,this)">
<input hidden name="csrfToken" value="a1e24s1">
<input name="email" value="a@b.com">
<input name="phone" value="123-456-789">
<input type="submit">
</form>


Look on chrome console>network before/after 'submit'

为了补充以上好的答案,你也可以避免在HTML中显式设置动作,并使用javascript中的事件处理程序,使用"this"作为表单来创建“;FormData"对象

Html表格:

<form id="mainForm" class="" novalidate>
<!--Whatever here...-->
</form>

在JS中:

$("#mainForm").submit(function( event ) {
event.preventDefault();
const formData = new URLSearchParams(new FormData(this));
fetch("http://localhost:8080/your/server",
{   method: 'POST',
mode : 'same-origin',
credentials: 'same-origin' ,
body : formData
})
.then(function(response) {
return response.text()
}).then(function(text) {
//text is the server's response
});
});

👨‍💻这些可以帮助你:

let formData = new FormData();
formData.append("name", "John");
formData.append("password", "John123");
fetch("https://yourwebhook", {
method: "POST",
mode: "no-cors",
cache: "no-cache",
credentials: "same-origin",
headers: {
"Content-Type": "form-data"
},
body: formData
});
//router.push("/registro-completado");
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
})
.catch(function(error) {
console.log("Error getting document:", error);
});

使用fetch api,你不需要包含头文件“content -type”:“multipart/form-data”。

所以下面的工作:

let formData = new FormData()
formData.append("nameField", fileToSend)


fetch(yourUrlToPost, {
method: "POST",
body: formData
})

注意,对于axios,我必须使用content-type。

@ kamilkieczzewski回答是伟大的,如果你是表单数据格式是在表单多部分风格,但如果你需要提交的表单查询参数风格:

如果你想生成查询参数,你也可以传递FormData直接到URLSearchParams构造函数,就像使用简单的GET提交一样。

        form = document.querySelector('form')
const formData = new FormData(form);
formData["foo"] = "bar";
const payload = new URLSearchParams(formData)
fetch(form.action, payload)

身体:FormData"工作,但有类型抱怨,还有&;FormData"设置多部分报头。为了使事情更简单,"身体:URLSearchParams"可以使用内联结构和手动设置的头文件:

function getAccessToken(code) {


return fetch(tokenURL,
{
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': '*/*'
},
body: new URLSearchParams({
'client_id':clientId,
'client_secret':clientSecret,
'code':code,
'grant_type': grantType,
'redirect_uri':'',
'scope':scope
})
}
)
.then(
r => return r.json()
).then(
r => r.access_token
)
}

MDN上有一些说明,浏览器将自动处理Content-Type:

如果在字典中没有设置内容类型头,请求也会自动设置一个内容类型头

所以当我们发送一个取回请求时,我们不需要指定'content-type'。

const formData = new FormData();
const fileField = document.querySelector('input[type="file"]');


formData.append('username', 'abc123');
formData.append('avatar', fileField.files[0]);


fetch('https://example.com/profile/avatar', {
method: 'PUT',
body: formData
})
.then(response => response.json())
.then(result => {
console.log('Success:', result);
})
.catch(error => {
console.error('Error:', error);
});

如果在头文件中设置content-type。浏览器将不会尝试分割请求有效负载中的表单数据。

我使用fathcer来处理FormData,与XHR的行为相同。

import { formData } from '@fatcherjs/middleware-form-data';
import { json } from '@fatcherjs/middleware-json';
import { fatcher } from 'fatcher';


fatcher({
url: '/bar/foo',
middlewares: [json(), formData()],
method: 'PUT',
payload: {
bar: 'foo',
file: new File()
},
headers: {
'Content-Type': 'multipart/form-data',
},
})
.then(res => {
console.log(res);
})
.catch(err => {
console.error(error);
});

内容-类型:“multipart /form-data"

const formData = new FormData(document.getElementById("form"))


fetch("http://localhost:8000/auth/token", {
method: "POST",
body: formData,
headers: {
"Content-Type": "multipart/form-data"
}
})

Content-Type:“application/x-www-form-urlencoded"

const formData = new URLSearchParams(new FormData(document.getElementById("form")))


fetch("http://localhost:8000/auth/token", {
method: "POST",
body: formData,
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
})