[英]How do I post form data with fetch api?
My code:我的代码:
fetch("api/xxx", {
body: new FormData(document.getElementById("form")),
headers: {
"Content-Type": "application/x-www-form-urlencoded",
// "Content-Type": "multipart/form-data",
},
method: "post",
}
I tried to post my form using fetch api, and the body it sends is like:我尝试使用 fetch api 发布我的表单,它发送的正文如下:
-----------------------------114782935826962
Content-Disposition: form-data; name="email"
test@example.com
-----------------------------114782935826962
Content-Disposition: form-data; name="password"
pw
-----------------------------114782935826962--
(I don't know why the number in boundary is changed every time it sends...) (我不知道为什么每次发送时边界中的数字都会改变......)
I would like it to send the data with "Content-Type": "application/x-www-form-urlencoded", what should I do?我希望它使用“Content-Type”发送数据:“application/x-www-form-urlencoded”,我该怎么办? Or if I just have to deal with it, how do I decode the data in my controller?
或者如果我只需要处理它,我如何解码控制器中的数据?
To whom answer my question, I know I can do it with:谁回答我的问题,我知道我可以做到:
fetch("api/xxx", {
body: "email=test@example.com&password=pw",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
method: "post",
}
What I want is something like $("#form").serialize() in jQuery (w/o using jQuery) or the way to decode mulitpart/form-data in controller.我想要的是 jQuery 中的 $("#form").serialize() (不使用 jQuery)或在控制器中解码 mulitpart/form-data 的方式。 Thanks for your answers though.
不过感谢您的回答。
To quote MDN on FormData
(emphasis mine):在
FormData
上引用 MDN (强调我的):
The
FormData
interface provides a way to easily construct a set of key/value pairs representing form fields and their values, which can then be easily sent using theXMLHttpRequest.send()
method.FormData
接口提供了一种方法来轻松构造一组表示表单字段及其值的键/值对,然后可以使用XMLHttpRequest.send()
方法轻松发送。 It uses the same format a form would use if the encoding type were set to"multipart/form-data"
.如果编码类型设置为
"multipart/form-data"
,它使用与表单相同的格式。
So when using FormData
you are locking yourself into multipart/form-data
.因此,当使用
FormData
时,您会将自己锁定在multipart/form-data
中。 There is no way to send a FormData
object as the body and not sending data in the multipart/form-data
format.无法将
FormData
对象作为正文发送,也不以multipart/form-data
格式发送数据。
If you want to send the data as application/x-www-form-urlencoded
you will either have to specify the body as an URL-encoded string, or pass a URLSearchParams
object.如果要将数据作为
application/x-www-form-urlencoded
发送,则必须将正文指定为 URL 编码字符串,或传递URLSearchParams
对象。 The latter unfortunately cannot be directly initialized from a form
element.遗憾的是后者不能直接从
form
元素初始化。 If you don't want to iterate through your form elements yourself (which you could do using HTMLFormElement.elements
), you could also create a URLSearchParams
object from a FormData
object:如果您不想自己遍历表单元素(可以使用
HTMLFormElement.elements
进行),您还可以从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(…);
Note that you do not need to specify a Content-Type
header yourself.请注意,您不需要自己指定
Content-Type
标头。
As noted by monk-time in the comments, you can also create URLSearchParams
and pass the FormData
object directly, instead of appending the values in a loop:正如评论中的和尚时间所指出的,您还可以创建
URLSearchParams
并直接传递FormData
对象,而不是在循环中附加值:
const data = new URLSearchParams(new FormData(formElement));
This still has some experimental support in browsers though, so make sure to test this properly before you use it.不过,这在浏览器中仍有一些实验性支持,因此请确保在使用之前对其进行正确测试。
Client客户
Do not set the content-type header.不要设置内容类型标头。
// Build formData object.
let formData = new FormData();
formData.append('name', 'John');
formData.append('password', 'John123');
fetch("api/SampleData",
{
body: formData,
method: "post"
});
Server服务器
Use the FromForm
attribute to specify that binding source is form data.使用
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; }
}
Use FormData
and fetch
to grab and send data使用
FormData
和fetch
抓取和发送数据
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'
You can set body
to an instance of URLSearchParams
with query string passed as argument您可以将
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>
With fetch api it turned out that you do NOT have to include headers "Content-type": "multipart/form-data".使用 fetch api,事实证明您不必包含标题“Content-type”:“multipart/form-data”。
So the following works:所以以下工作:
let formData = new FormData()
formData.append("nameField", fileToSend)
fetch(yourUrlToPost, {
method: "POST",
body: formData
})
Note that with axios I had to use the content-type.请注意,使用 axios 我必须使用内容类型。
👨💻These can help you: 👨💻这些可以帮助你:
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);
});
To add on the good answers above you can also avoid setting explicitly the action in HTML and use an event handler in javascript, using "this" as the form to create the "FormData" object要添加上面的好答案,您还可以避免在 HTML 中明确设置操作并在 javascript 中使用事件处理程序,使用“this”作为创建“FormData”对象的表单
Html form : html格式:
<form id="mainForm" class="" novalidate>
<!--Whatever here...-->
</form>
In your JS :在你的 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
});
});
@KamilKiełczewski answer is great if you are okay with the form data format being in form multipart style, however if you need the form submitted in query parameter styles: @KamilKiełczewski 如果您对表单数据格式采用表单多部分样式没问题,那么答案非常好,但是如果您需要以查询参数样式提交的表单:
You can also pass FormData directly to the URLSearchParams constructor if you want to generate query parameters in the way a would do if it were using simple GET submission.
如果您想以使用简单 GET 提交的方式生成查询参数,也可以将FormData 直接传递给 URLSearchParams 构造函数。
form = document.querySelector('form')
const formData = new FormData(form);
formData["foo"] = "bar";
const payload = new URLSearchParams(formData)
fetch(form.action, payload)
" body:FormData " works but there're type complains, also " FormData " sets multipart headers. “ body:FormData ” 有效,但有类型抱怨,“ FormData ” 设置多部分标题。 To make the things simplier, " body:URLSearchParams " with inline construction and headers set manually may be used :
为了使事情变得更简单,可以使用具有内联结构和手动设置标题的“ body: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
)
}
There are instructions on the MDN that the browser will automatically handle Content-Type
. MDN 上有关于浏览器将自动处理
Content-Type
说明。
[A request will also automatically set a Content-Type header if none is set in the dictionary.](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#body)
[如果字典中没有设置,请求也会自动设置 Content-Type 头。](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#body)
So we don't need to specify 'content-type' when we send a fetch request.所以我们在发送 fetch 请求时不需要指定 '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);
});
If set content-type
in headers.如果在标题中设置
content-type
。 Browser will not try to split formdata in request payload.浏览器不会尝试在请求负载中拆分表单数据。
I'm using fathcer to handle FormData, the same behavior as XHR.我正在使用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);
});
To post form data with fetch api, try this code it works for me ^_^要使用 fetch api 发布表单数据,试试这个对我有用的代码 ^_^
function card(fileUri) {
let body = new FormData();
let formData = new FormData();
formData.append('file', fileUri);
fetch("http://X.X.X.X:PORT/upload",
{
body: formData,
method: "post"
});
}
Use this for a JSON api:将此用于 JSON api:
async function write(param) {
var zahl = param.getAttribute("data-role");
let mood = {
appId: app_ID,
key: "",
value: zahl
};
let response = await fetch(web_api, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(mood)
});
console.log(currentMood);
}
async function get() {
let response = await fetch(web_api + "/App/" + app_ID, {
method: "GET",
headers: {
"Content-Typ": "application/json"
}
});
let todos = await response.json();
function remove() {
return fetch(web_api, {
method: "DELETE"
}).then(response => {
if (!response.ok) {
throw new Error("There was an error processing the request");
}
});
}
function updateTodo() {
return fetch(web_api, {
method: "PUT",
body: JSON.stringify(todo),
headers: {
"Content-Type": "application/json",
},
}).then((response) => {
if (!response.ok) {
throw new Error("There was an error processing the request");
}
});
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.