如何使用抓取 API 发布表单数据?

2022-08-30 00:26:07

我的代码:

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--

(我不知道为什么边界中的数字每次发送时都会改变...)

我希望它使用“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",
}

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


答案 1

引用MDN关于FormData(强调我的):

FormData 接口提供了一种方法来轻松构造一组表示表单字段及其值的键/值对,然后可以使用该方法轻松发送这些键/值对。它使用的格式与编码类型设置为“多部分/表单数据”时表单使用的格式相同XMLHttpRequest.send()

因此,在使用时,您将将自己锁定在.没有办法将对象作为正文发送而不以该格式发送数据。FormDatamultipart/form-dataFormDatamultipart/form-data

如果要发送数据,则必须将正文指定为 URL 编码的字符串,或者传递 URLSearchParams 对象。不幸的是,后者不能直接从元素初始化。如果您不想自己循环访问表单元素(可以使用 HTMLFormElement.elements 执行此操作),也可以从对象创建一个对象:application/x-www-form-urlencodedformURLSearchParamsFormData

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在注释中指出的那样,您还可以直接创建和传递对象,而不是在循环中附加值:URLSearchParamsFormData

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

不过,这在浏览器中仍然有一些实验性支持,因此请确保在使用之前对其进行正确测试。


答案 2

客户

不要设置内容类型标头。

// 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; }
}